- 网络协议栈流程图以及数据结构
linux内核网络模块加载
socket 创建流程
UDP 收发包流程以及 软中断收发包流程
UDP 收-发包流程
-> igb_msix_ring 中断服务函数(分队列处理) -> napi_schedule -> napi_schedule_prep 检测napi->state, NAPI_STATE_SCHED是否置位允许napi调度 -> __napi_schedule -> ____napi_schedule 关闭硬件中断,并将该napi->poll_list添加到全局轮询队列poll_list -> __raise_softirq_irqoff(NET_RX_SOFTIRQ) 产生napi软件中断 -> net_rx_action 软中断服务函数 只要全局poll_list队列不为空,则一直轮询处理 当轮询完成预设目标任务budget,或者2秒轮询超时后强制退出则结束napi轮询,重新使能中断 -> n->poll -> igb_poll 回调网卡轮询处理接口 -> igb_clean_rx_irq -> igb_alloc_rx_buffers 判断回收rx_buffer超过IGB_RX_BUFFER_WRITE(16),一次性补充16个buffer -> igb_fetch_rx_buffer 申请skb并将rx_buffer数据page挂接到skb -> napi_gro_receive 判断网卡是否支持GRO(Generic Segmentation Offload) 相对应的有TSO(TCP Segmentation Offload) -> napi_skb_finish -> netif_receive_skb 使能CONFIG_RPS(Receive Packet Steering)时 -> get_rps_cpu 依据skb->hash获取后续传输层协议栈处理target CPU -> enqueue_to_backlog -> __skb_queue_tail 将各个队列的skb入列到对应处理target CPU的input_pkt_queue -> ____napi_schedule -> __raise_softirq_irqoff(NET_RX_SOFTIRQ) 产生sd->backlog软件中断 -> net_rx_action 软中断服务函数 -> n->poll -> process_backlog 回调backlog的轮询处理函数 -> __skb_dequeue 从队列中出列待处理skb -> __netif_receive_skb -> __netif_receive_skb_core 开始处理网络层skb 根据注册skb->protocol搜索pt_prev /* Protocol hook */ -> deliver_skb -> pt_prev->func -> ip_rcv IP层数据处理,net/ipv4/af_inet.c注册 若注册pf_ring的packet_type,则调用pfring rcv prot_hook.func = packet_rcv; prot_hook.type = htons(ETH_P_ALL); -> ip_rcv_finish -> dst_input /* Input packet from network to transport */ -> skb_dst(skb)->input(skb) -> ip_local_deliver -> ip_defrag /* Reassemble IP fragments. */ -> ip_local_deliver_finish 根据注册inet_protos搜索ipprot tcp_protocol, udp_protocol, icmp_protocol, igmp_protocol等 在net/ipv4/af_inet.c,inet_init注册,以tcp为例 -> tcp/udp层 -> ipprot->handler -> tcp_v4_rcv(udp_rcv) -> tcp_v4_do_rcv -> tcp_rcv_state_process -> case TCP_ESTABLISHED: tcp_data_queue -> tcp_queue_rcv -> __skb_queue_tail /* queue a buffer at the list tail */ -> napi_complete 结束轮询 -> igb_ring_irq_enable 重新使能硬件中断 应用层send -> copy_from_user -> 内核层skb -> 协议栈 -> 分队列 -> ndo_start_xmit -> igb_xmit_frame -> igb_xmit_frame_ring -> igb_tx_queue_mapping 根据skb->queue_mapping获取对应发送队列tx_ring -> igb_xmit_frame_ring skb填充tx_ring->tx_buffer_info -> igb_tso TSO(TCP Segmentation Offload) -> igb_tx_map 将skb流式映射dma_map_single填充描述符tx_desc 并在最后一帧的描述符tx_desc中将EOP(End of Packet)置位 -> igb_msix_ring 中断服务函数(分队列处理) -> napi_schedule -> napi_schedule_prep 检测napi->state, NAPI_STATE_SCHED是否置位允许napi调度 -> __napi_schedule -> ____napi_schedule 关闭硬件中断,并将该napi->poll_list添加到全局轮询队列poll_list -> __raise_softirq_irqoff(NET_RX_SOFTIRQ) 产生napi软件中断 -> net_rx_action 软中断服务函数 只要全局poll_list队列不为空,则一直轮询处理 当轮询完成预设目标任务budget,或者2秒轮询超时后强制退出则结束napi轮询,重新使能中断 -> n->poll -> igb_poll 回调网卡轮询处理接口 -> igb_clean_tx_irq 释放skb,dma_unmap_single