每个类型的网卡都存在一个设备驱动程序。在驱动程序内部,Linux 总是会调用一个标准的高级路由函数:“netif_rx [net/core/dev.c]”,该函数会控制帧属于哪个 3 层协议,并且会调用正确的 3 层函数(因此我们将使用函数指针来确定哪个是正确的函数)。
现在我们将看到一个示例,说明当我们将 TCP 数据包发送到 Linux 时会发生什么,从调用 “netif_rx [net/core/dev.c]” 开始。
|netif_rx |__skb_queue_tail |qlen++ |* simple pointer insertion * |cpu_raise_softirq |softirq_active(cpu) |= (1 << NET_RX_SOFTIRQ) // set bit NET_RX_SOFTIRQ in the BH vector
函数
一旦 IRQ 交互结束,我们需要继续跟踪帧生命周期的下一部分,并检查 NET_RX_SOFTIRQ 的作用。
接下来,我们将根据 "net_dev_init [net/core/dev.c]" 调用 “net_rx_action [net/core/dev.c]”。
|net_rx_action |skb = __skb_dequeue (the exact opposite of __skb_queue_tail) |for (ptype = first_protocol; ptype < max_protocol; ptype++) // Determine |if (skb->protocol == ptype) // what is the network protocol |ptype->func -> ip_rcv // according to ''struct ip_packet_type [net/ipv4/ip_output.c]'' **** NOW WE KNOW THAT PACKET IS IP **** |ip_rcv |NF_HOOK (ip_rcv_finish) |ip_route_input // search from routing table to determine function to call |skb->dst->input -> ip_local_deliver // according to previous routing table check, destination is local machine |ip_defrag // reassembles IP fragments |NF_HOOK (ip_local_deliver_finish) |ipprot->handler -> tcp_v4_rcv // according to ''tcp_protocol [include/net/protocol.c]'' **** NOW WE KNOW THAT PACKET IS TCP **** |tcp_v4_rcv |sk = __tcp_v4_lookup |tcp_v4_do_rcv |switch(sk->state) *** Packet can be sent to the task which uses relative socket *** |case TCP_ESTABLISHED: |tcp_rcv_established |__skb_queue_tail // enqueue packet to socket |sk->data_ready -> sock_def_readable |wake_up_interruptible *** Packet has still to be handshaked by 3-way TCP handshake *** |case TCP_LISTEN: |tcp_v4_hnd_req |tcp_v4_search_req |tcp_check_req |syn_recv_sock -> tcp_v4_syn_recv_sock |__tcp_v4_lookup_established |tcp_rcv_state_process *** 3-Way TCP Handshake *** |switch(sk->state) |case TCP_LISTEN: // We received SYN |conn_request -> tcp_v4_conn_request |tcp_v4_send_synack // Send SYN + ACK |tcp_v4_synq_add // set SYN state |case TCP_SYN_SENT: // we received SYN + ACK |tcp_rcv_synsent_state_process tcp_set_state(TCP_ESTABLISHED) |tcp_send_ack |tcp_transmit_skb |queue_xmit -> ip_queue_xmit |ip_queue_xmit2 |skb->dst->output |case TCP_SYN_RECV: // We received ACK |if (ACK) |tcp_set_state(TCP_ESTABLISHED)
函数可以在以下位置找到
描述
SERVER (LISTENING) CLIENT (CONNECTING) SYN <------------------- SYN + ACK -------------------> ACK <------------------- 3-Way TCP handshake