我正在尝试理解Linux内核中的NAPI实现。这些是我的基本疑虑。
1)NAPI禁用进一步的中断并使用轮询处理skbs
中断处理程序是否应禁用它?
如果是 - 禁用中断和处理实际轮询的SOFTIRQ net_rx_action之间的时间差距是不是太大了。
2)默认情况下,所有启用NAPI的驱动程序在接收单帧时禁用中断并使用下半部分轮询处理剩余帧? 或者是否有逻辑,其中只有框架> 32(在连续接收irq处理程序中的所有帧时)切换到轮询模式?
3)现在来到SHARED IRQ -
答案 0 :(得分:5)
我写了一本关于understanding, tuning, and optimizing the Linux network stack的综合指南,它解释了有关网络驱动程序,NAPI等的所有内容,请查看。
至于你的问题:
在启用NAPI后,驱动程序的IRQ处理程序应禁用设备IRQ。是的,存在时间差,但它应该很小。这是您必须做出的权衡决定的一部分:您是否更关心吞吐量或延迟?根据具体情况,您可以适当地优化网络堆栈。在任何情况下,大多数NIC允许用户增加(或减少)跟踪传入网络数据的环形缓冲区的大小。因此,暂停很好,因为数据包将稍后排队等待处理。
这取决于驱动程序,但通常大多数驱动程序将在IRQ处理程序中启用NAPI轮询模式,只要通过调用napi_schedule
(通常)触发它。您可以找到如何NAPI is enabled for the Intel igb driver here.的演练。请注意,不必为每个数据包触发IRQ处理程序。您可以使用名为interrupt coalescing的功能调整IRQ处理程序在大多数卡上触发的速率。某些NIC可能不支持此选项。
当IRQ被触发时,将执行其他设备的IRQ处理程序,因为IRQ处理程序在CPU上具有非常高的优先级。 NAPI轮询循环(在SoftIRQ中运行)将在设备IRQ处理的任何CPU上运行。因此,如果您有多个NIC和多个CPU,则可以调整每个NIC的IRQ的IRQ亲和性,以防止使特定NIC匮乏。
至于你在评论中提到的例子:
假设NIC 1和NIC 2共享IRQ线,假设NIC 1为低负载,NIC 2为高负载且NIC 1接收中断,NIC 1的驱动程序将禁用中断,直到它的softirq被处理为止,称时间间隔为t1 。所以对于时间t1,NIC 2的中断过于禁用,对吧?
这取决于驱动程序,但在正常情况下,NIC 1仅在执行IRQ处理程序时禁用中断。对napi_schedule
的调用告诉softirq代码,如果尚未启动它应该开始运行。 softirq代码异步运行,因此没有NIC 1不等待softirq被处理。
现在,就共享IRQ而言:再次取决于设备和驱动程序。应该以能够处理共享IRQ的方式编写驱动程序。如果驱动程序禁用正在共享的IRQ,则共享该IRQ的所有设备都不会收到中断。这会很糟糕。某些设备解决此问题的一种方法是允许驱动程序读取/写入特定寄存器,从而导致该特定设备停止生成中断。这是一个首选解决方案,因为它不会阻止生成相同IRQ的其他设备。
当为NAPI禁用IRQ时,意味着驱动程序要求NIC硬件停止发送IRQ。因此,同一行(对于其他设备)的其他IRQ仍将继续处理。以下是Intel igb driver如何通过写入寄存器来关闭该器件的IRQ的示例。