当前位置:首页>Linux>linux内核协议栈之tcp connect流程(二)

linux内核协议栈之tcp connect流程(二)

  • 2026-10-11 08:18:43
linux内核协议栈之tcp connect流程(二)

tcp三次握手服务端处理流程,如图1-1所示。

图1-1:函数tcp_v4_rcv代码流程图

  1. 网卡驱动收到数据后,会触发NET_RX_SOFTIRQ软中断,软中断处理函数net_rx_action通过调用网卡驱动注册的poll函数来进行收包处理,最终通过netif_receive_skb->ip_rcv ip_rcv_finish->dst_input->ip_local_deliver->ip_local_deliver_finish->tcp_v4_rcv来进行tcp收包处理。tcp_v4_do_rcv首先根据目标ip与端口查找已经建立连接的sock,如果以前没有建立连接则在listen端口中查找,找到以后首先,将tcp头中的相关信息填入skb私有数据区cb中。然后调用tcp_v4_do_rcv进行真正的syn请求处理。
  2. __inet_lookup_skb函数主要是sk查找函数,它首先在tcp_hashinfo实例的ehash链表中查找,找不到就会在监听sock所在的hash表中查找,对于第一次同步请求,返回的结果是listen sk,此时sk->sk_state状态是TCP_LISTEN。
  3. tcp_v4_fill_cb函数主要是将tcp头中的start seq、end seq、ark seq等信息填入skbcb中。
  4. 由于此时sk->sk_state状态是TCP_LISTEN,因此进入tcp_v4_do_rcv流程,它根据sk_state会继续调用tcp_rcv_state_process函数。
  5. tcp_rcv_state_process函数根据sk->sk_state状态,来查看是否是syn请求消息,如是则继续调用icsk->icsk_af_ops->conn_request,icsk->icsk_af_ops指针的初使化是在tcp_prot: tcp_v4_init_sock函数中,此初使化函数将icsk->icsk_af_ops 赋值为 &ipv4_specific,因此,icsk->icsk_af_ops->conn_request函数对应ipv4_specific:tcp_v4_conn_request函数。
  6. 对于ipv4_specific:tcp_v4_conn_request函数,它会调用真正的处理函数tcp_conn_request,如图1-2所示。
    图1-2:函数tcp_v4_conn_request代码流程图
  7. 主要调用tcp_conn_request来进行真正处理。
  8. Syn请求真正的处理函数,它首先判断syn请求队列是否已达最大值,通过检查后,会分配一个req(struct request_sock *req)实例,且req->rsk_listener 赋值为 listener sk,req->rsk_ops赋值为tcp_request_sock_ops,req_to_sk(req)->sk_prot 赋值为 sk_listener->sk_prot,ireq->ireq_state 赋值为 TCP_NEW_SYN_RECV,接着赋值tcp_rsk(req)->af_specific 为tcp_request_sock_ipv4_ops,然后调用tcp_openreq_init继续初使化req相关结构,包括源端口与目标端口,调用af_ops->init_req设置源ip与目标ip,接着需给对端响应syn ack,因此调用af_ops->route_req查找目标路由,调用tcp_openreq_init_rwin初使化syn ack相关字段,接着调用inet_csk_reqsk_queue_hash_add将req保存到tcp_hashinfo实例的ehash链表中,最后调用af_ops->send_synack给对端响应syn ack。
  9. 判断syn请求队列是否达到最大值。
  10. inet_reqsk_alloc分配syn ack实例req,并初使化部分成员,如:req->rsk_listener 赋值为 listener sk,req->rsk_ops赋值为tcp_request_sock_ops,req_to_sk(req)->sk_prot 赋值为 sk_listener->sk_prot,ireq->ireq_state 赋值为 TCP_NEW_SYN_RECV。
  11. tcp_openreq_init函数继续为req实例赋值,主要有:ireq->ir_rmt_port赋值为syn请求的源端口,ireq->ir_num赋值为同步请求的目的端口,tcp_rsk(req)->rcv_isn赋值为syn请求的start seq等。
  12. af_ops->init_req函数对应tcp_request_sock_ipv4_ops:tcp_v4_init_req,它主要是设置同步请求的源ip与目标ip。
  13. 接着需根据syn请求源ip查找syn ack消息的路由。
  14. tcp_openreq_init_rwin主要是生成syn ack响应消息中的tcp windows字段。
  15. 将req请求插入到tcp_hashinfo实例的ehash链表中。
  16. af_ops->send_synack函数主要是回复syn ack,此处对应函数tcp_request_sock_ipv4_ops:tcp_v4_send_synack。它首先调用tcp_make_synack生成syn ack的skb并记录当前时间到skb->skb_mstamp_ns中,然后调用ip_build_and_send_pkt->ip_local_out将其发送出去。

参考

linux内核版本:5.7.8

最新文章

随机文章