linux kernel 工程师
全部博文(99)
分类: LINUX
2014-02-11 12:09:44
process_backlog是softnet_data->backlog的poll函数, 作为非NAPI接口的处理函数
net_rx_action调用poll函数时会使用它。
static int process_backlog(struct napi_struct *napi, int quota)
{
int work = 0;
struct softnet_data *sd = container_of(napi, struct softnet_data, backlog);
#ifdef CONFIG_RPS
/* Check if we have pending ipi, its better to send them now,
* not waiting net_rx_action() end.
*/
if (sd->rps_ipi_list) {
local_irq_disable();
net_rps_action_and_irq_enable(sd);
}
#endif
napi->weight = weight_p;
local_irq_disable();
while (work < quota) {
struct sk_buff *skb;
unsigned int qlen;
while ((skb = __skb_dequeue(&sd->process_queue))) { //skb实际上从process_queue取下,而不是直接从input_pkt_queue取下
local_irq_enable();
__netif_receive_skb(skb); //交给ip层处理
local_irq_disable();
input_queue_head_incr(sd);
if (++work >= quota) {// 不能超过配额
local_irq_enable();
return work;
}
}
rps_lock(sd);
qlen = skb_queue_len(&sd->input_pkt_queue);
//将input_pkt_queue并入process_queue
if (qlen)
skb_queue_splice_tail_init(&sd->input_pkt_queue,
&sd->process_queue);
//如果总的工作量不超过配额,说明本次就可以处理完毕,将backlog从softnet的poll_list上拿下
if (qlen < quota - work) {
/*
* Inline a custom version of __napi_complete().
* only current cpu owns and manipulates this napi,
* and NAPI_STATE_SCHED is the only possible flag set on backlog.
* we can use a plain write instead of clear_bit(),
* and we dont need an smp_mb() memory barrier.
*/
list_del(&napi->poll_list);
napi->state = 0;
quota = work + qlen; //调整quota至work + qlen,而不必等到原先分配的weight
}
rps_unlock(sd);
}
local_irq_enable();
return work;
}