/usr/src/linux-2.6.19/net/core/dev.c

static void net_rx_action(struct softirq_action *h)
{
    struct  softnet_data  *queue = &__get_cpu_var(softnet_data);
    unsigned long start_time = jiffies;
    int budget =  netdev_budget ;                            //(1)
    void *have;
    local_irq_disable();                                   //(2)

     while (!list_empty(&queue->poll_list)) {                //(3)
        struct  net_device  *dev;
        if (budget <= 0 || jiffies - start_time > 1)       //(4)
            goto  softnet_break ;
        local_irq_enable();                                //(5)
        dev = list_entry(queue->poll_list.next,
                 struct net_device, poll_list);            //(6)

        have = netpoll_poll_lock(dev);
        if (dev->quota <= 0 ||  dev->poll (dev, &budget)) { -//(7) 
            netpoll_poll_unlock(have);
            local_irq_disable();                           //(8)
            list_move_tail(&dev->poll_list, &queue->poll_list);
            if (dev->quota < 0)                            //(9)
                dev->quota += dev->weight;
            else
                dev->quota = dev->weight;
        } else {
            netpoll_poll_unlock(have);
            dev_put(dev);
            local_irq_disable();
        }
     }

out:
#ifdef CONFIG_NET_DMA
    if (net_dma_client) {
        struct dma_chan *chan;
        rcu_read_lock();
        list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
            dma_async_memcpy_issue_pending(chan);
        rcu_read_unlock();
    }
#endif

    local_irq_enable();                                  //(10)
    return;

softnet_break:
    __get_cpu_var(netdev_rx_stat).time_squeeze++;
    __raise_softirq_irqoff(NET_RX_SOFTIRQ);
    goto out;
}

(1) 表示队列的最大长度,在这里定义了一次中断处理skb的数目,系统定义为300
/usr/src/linux-2.6.19/net/core/dev.c
int  netdev_budget  = 300;
(2) 禁止中断
(3) 检查POLL队列(poll_list)上是否有设备在准备等待轮询
(4) 这里保证执行当前POLL过程的时间不超过一个时间片,这样不至于被软中断占用太多的时间
(5) 开中断
(6) 从公共的softnet_data数据结构中的轮循队列上获得等待轮循的设备结构
(7) 调用设备的POLL方法从NIC上的Ring Buffer中读入数据
    真正的数据处理是在dev->poll()中进行的 。poll方法在net_dev_init的时候被指定为process_backlog(),它调用netif_receive_skb()对skb数据进行了接收
(8) 因为要对poll_list进行操作这个操作也不能被中断所以要关中断
(9) 完成一次POLL过程的数据的接收,重新定义设备接收数据的"配额" -- quota(事实上就是sk_buff缓冲区的数量,每次调用POLL方法的时候可以创建并且最多可以向上层提交的sk_buff缓冲区数目,这个参数很重要在高速处理的时候有需要慎重优化这个数值,在有大量数据接收的情况下,需要增加该数值)
(10)完成更新打开中断

Logo

更多推荐