netif_rx()处理过程

netif_rx()处理过程_第1张图片

int netif_rx(struct sk_buff *skb)
{
	struct softnet_data *queue;
	unsigned long flags;

	//netpoll是否会使用此skb 
	if (netpoll_rx(skb))
		return NET_RX_DROP;

    //设置包接收的时间戳
	if (!skb->tstamp.tv64)
		net_timestamp(skb);

	//禁止本地cpu中断
	local_irq_save(flags);
	/* 获取当前CPU的 softnet_data 数据 */
	queue = &__get_cpu_var(softnet_data);

	//更新统计信息 接收帧的总数
	__get_cpu_var(netdev_rx_stat).total++;

	//netdev_max_backlog输入队列最大长度 在此2.6.32版本默认为1000
	if (queue->input_pkt_queue.qlen <= netdev_max_backlog) 
	{
	     //队列是否为空 
		if (queue->input_pkt_queue.qlen) 
		{
enqueue:
	        //将数据包加入到接收队列中
			__skb_queue_tail(&queue->input_pkt_queue, skb);
			
            //回复本地cpu中断
			local_irq_restore(flags);
			return NET_RX_SUCCESS;
		}

		//触发NET_RX_SOFTIRQ类型软中断  net_rx_action
		//只有当队列为空的时候才会调度 是由于队列不为空 接收软中断已经被调用一次,没必要在调用一次
		napi_schedule(&queue->backlog);
		goto enqueue;
	}

	//增加统计信息报丢弃的数量
	__get_cpu_var(netdev_rx_stat).dropped++;

	//恢复本地cou中断
	local_irq_restore(flags);

	//处理完后释放skb
	kfree_skb(skb);
	return NET_RX_DROP;
}

 

你可能感兴趣的:(内核网络)