报文接收步骤:
2、中断处理函数首先禁用网卡的接收报文中断。
3、接着负责在内存中申请一个skb,把网卡硬件缓存中的报文拷贝到skb中。
初始化skb的一些字段,根据报文内容给skb->protocol字段赋值,例如ip报文会赋为0x0800。
4、接着调用netif_rx()把skb放入本地CPU的接收队列softnet_data->input_pkt_queue。
如果本地CPU的接收队列softnet_data->input_pkt_queue为空,会把特殊的napi backlog(初始化:dev.c/net_dev_init())挂到softnet_data->poll_list上。
5、接着使能网卡收包中断。中断处理函数退出。在中断处理函数退出时会调度报文接收软中断进行处理CPU上的接收队列softnet_data->input_pkt_queue中的报文。
6、在收包软中断中会找到本地CPU的softnet_data的poll_list链表,调用特殊napi backlog的轮询函数process_backlog()来处理报文。
一、旧的接收过程
1、当网卡中断产生后,内核的中断处理部分会根据网卡驱动注册的中断号找到相应网卡驱动中的中断处理函数。2、中断处理函数首先禁用网卡的接收报文中断。
3、接着负责在内存中申请一个skb,把网卡硬件缓存中的报文拷贝到skb中。
初始化skb的一些字段,根据报文内容给skb->protocol字段赋值,例如ip报文会赋为0x0800。
4、接着调用netif_rx()把skb放入本地CPU的接收队列softnet_data->input_pkt_queue。
如果本地CPU的接收队列softnet_data->input_pkt_queue为空,会把特殊的napi backlog(初始化:dev.c/net_dev_init())挂到softnet_data->poll_list上。
5、接着使能网卡收包中断。中断处理函数退出。在中断处理函数退出时会调度报文接收软中断进行处理CPU上的接收队列softnet_data->input_pkt_queue中的报文。
6、在收包软中断中会找到本地CPU的softnet_data的poll_list链表,调用特殊napi backlog的轮询函数process_backlog()来处理报文。
7、轮询函数process_backlog()循环从softnet_data的输入队列input_pkt_queue取报文并将其送到协议栈相关协议模块进行处理(netif_receive_skb(skb)),直到队列中没有报文了,或处理的报文数大于了允许的上限值了,或轮询函数执行时间大于一个jiffies了。
从网卡硬件缓存中把报文拷贝到内存放在硬件中断处理中做,把协议栈处理报文的工作放在软中断做,这样提高了对硬件中断的响应速度