linux网络收包流程
简介
本文主要关注转发相关流程。并以igb驱动举例。⾸先当数据帧从⽹线到达⽹卡上的时候,第⼀站是⽹卡的接收队列。⽹卡在分配给⾃⼰的RingBuffer 中寻找可⽤的内存位置,找到后 DMA 引擎会把数据 DMA 到⽹卡之前关联的内存⾥,这个时候 CPU 都是⽆感的。当 DMA 操作完成以后,⽹卡会向 CPU 发起⼀个硬中断,通知 CPU 有数据到达。
网卡驱动会注册一个终端服务函数,以igb驱动为例,通过request_irq,注册了一个终端服务程序igb_msix_ring。所以当有dma的中断会发给igb_msix_ring
网络收包流程-中断服务处理部分
- igb_msix_ring,调用napi_schedule,继续调用__napi_schedule。
- __napi_schedule,首先关中断,调用____napi_schedule,然后再开中断。通过这样减少中断的次数。
- ____napi_schedule,把数据加入poll_list,然后发送软中断信号NET_RX_SOFTIRQ,进入软中断处理
网络收包流程-软中断处理部分
- 通过NET_RX_SOFTIRQ,进入net_rx_action处理,在net_rx_action会编译poll_list,调用napi_poll
- napi_poll会调用igb_poll,
- igb_poll调用igb_clean_rx_irq,
- igb_clean_rx_irq,会调用napi_gro_receive
- napi_gro_receive会调用napi_skb_finish
- napi_gro_receive调用netif_receive_skb_internal
- netif_receive_skb_internal调用__netif_receive_skb
- netif_receive_skb_internal调用__netif_receive_skb_core
- __netif_receive_skb_core会进入协议栈
igb_msix_ring-->
napi_schedule-->
__napi_schedule-->
____napi_schedule--NET_RX_SOFTIRQ-->
net_rx_action-->
napi_poll-->
igb_poll-->
igb_clean_rx_irq-->
napi_gro_receive-->
netif_receive_skb_internal-->
__netif_receive_skb-->
__netif_receive_skb_core
__netif_receive_skb_core之后的流程,可参考,nfq内核流程
RPS收包流程
RPS收包流程会有两次进入软中断的过程。
- 软中断最终调用netif_receive_skb_internal,因为开启了RPS功能,所以按cpu把包放进了enqueue_to_backlog。
- enqueue_to_backlog把包都放入input_pkt_queue队列,第一次把对应的sd->backlog(backlog.poll=process_backlog),放入sd->poll_list,再次出发软中断。
- 之前的net_rx_action遍历完poll_list,把数据都添加到input_pkt_queue。处理完之后再次收软中断进入net_rx_action,napi_poll调用process_backlog。
- process_backlog把input_pkt_queue移到process_queue。再遍历process_queue。调用__netif_receive_skb把数据发送出去。
net_rx_action-->
napi_poll-->
igb_poll-->
igb_clean_rx_irq-->
napi_gro_receive-->
netif_receive_skb_internal-->
enqueue_to_backlog-->input_pkt_queue
net_rx_action-->
napi_poll-->
process_backlog--input_pkt_queue--process_queue->
__netif_receive_skb-->
__netif_receive_skb_core