- 论坛徽章:
- 0
|
NAPI的由来:
NAPI是2.4.20后的内核版本在网卡驱动做的一项优化措施,当年某个商业测试2.2的Linux和Winnt的网络效率,Linux在小包处理吞吐量输了,这个报告引起了很大的争议,后来Linux在驱动采取了一系列的优化措施,NAPI是很重要的一个。
NAPI的原理: 一般情况下,每接收到一个帧,都会出发一次网络中断,然后软中断处理这个报文,直到报文到目的地(转发或用户socket buffer).
现在的做法,大流量情况下,收中断是不启用的。这样收帧不会频繁触发网络中断,而是报文到了一定数量后触发一次中断,如8139网卡。在cp_interrupt()中,会调用NAPI的接口,将网卡加入到softirq任务链表中,然后唤醒softirq, 在softirq中,回调dev中的接口批量处理报文。
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
if (netif_rx_schedule_prep(dev)) {
cpw16_f(IntrMask, cp_norx_intr_mask);
__netif_rx_schedule(dev);
}
__netif_rx_schedule() -->
{
unsigned long flags;
raw_local_irq_save(flags);
dev_hold(dev);
/* 将dev加入到软中断处理链表中 */
list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
if (dev->quota < 0)
dev->quota += dev->weight;
else
dev->quota = dev->weight;
/* 唤醒软中断 */
raise_softirq_irqoff(NET_RX_SOFTIRQ);
raw_local_irq_restore(flags);
}
软中断处理中,会利用dev->poll() 函数,实现一次软中断,处理大量报文,如8139
cp_rx_poll() -->
批量处理网卡buffer中的报文。
softirq处理过程也有同样的优化,正常情况下,所有的报文都是在软中断中完成,但是当软中断一直有处理不完的报文,为了提高系统实时行,软中断处理完一定数量的报文后,必须退出,剩余的报文通过唤醒softirqd 内核线程来完成。
void ___do_softirq(void) -->
/* 如果处理一轮后,仍然后报文要处理,唤醒softirqd任务代为处理 */
if (pending)
trigger_softirqs();
trigger_softirqs()-->
static void trigger_softirqs(void)
{
u32 pending = local_softirq_pending();
int curr = 0;
while (pending) {
if (pending & 1)
/* 唤醒softirqd */
wakeup_softirqd(curr);
pending >>= 1;
curr++;
}
}
内核: 2.6.15-rt2 |
|