3 网络接收软件中断
网络系统的软中断接收处理程序是net_rx_action()。net_rx_action()的任务是将数据帧推送到上层TCP/Ip协议进行处理。要推送给上层协议的数据可以从两个地方获取。
² 多个设备共享的CPU输入队列。不支持NAPI的网络设备的中断处理程序掉netif_rx函数,把数据帧放在当前执行中断处理程序的CPU的输入队列中。net_rx_action()从输入队列中获取数据帧传给上层协议,CPU的输入队列由所有不支持NAPi的网络设备共享。
² 设备硬件缓冲区。支持NAPi的网络设备驱动程序用poll函数直接从设备硬件缓冲区中读出数据帧推送给上层协议。
软件流程
4 从输入队列中读取数据
CPU对立softnet_data的poll虚函数,初始化为默认的process_backlog,为不支持NAPI的设备来处理队列中的数据帧。分析netif_rx的执行流程,发现netif_rx函数在接收到第一个网络数据帧时,会将处理CPU输入队列数据帧的上传函数process_backlog放到当前CPU的poll_list队列,在net_rx_action()函数中调用执行。
if (test_bit(NAPI_STATE_SCHED,&n->state)
work = n->poll(n,weight);
static int process_backlog(struct napi_struct *napi, int quota) { int work = 0; struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies;
napi->weight = weight_p; do { struct sk_buff *skb; struct net_device *dev;
local_irq_disable(); //从CPU输入队列中获取数据帧skb skb = __skb_dequeue(&queue->input_pkt_queue); //如果队列空,则将设备移出poll_list队列 if (!skb) { __napi_complete(napi); local_irq_enable(); break; }
local_irq_enable();
dev = skb->dev; //调用netif_receive_skb将skb传送给上层协议 netif_receive_skb(skb);
dev_put(dev); } while (++work < quota && jiffies == start_time);
return work; } |
此处有个问题需要解决?
怎么知道放入输入队列的数据是哪个设备的?
现在分析下执行到process_backlog时,一些数据结构的问题。
这主要是通过skb中的dev数据域,将数据和设备联系起来了。而napi_struct中又有dev指针域,和设备联系起来,通过各个结构体中的指针,从而将数据与设备联系起来。