关于 Linux 内核中的 NAPI 实现 [英] Regarding NAPI implementation in Linux kernel

查看:22
本文介绍了关于 Linux 内核中的 NAPI 实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解启用 NAPI 的网络驱动程序,但对此有一些疑问.

I am trying to understand the NAPI enabled Network driver and have some doubts regarding the same.

如果我用外行的话说,每当网络数据包到达接口时,它都会通知 CPU 并执行适当的以太网驱动程序(中断处理程序)代码.以太网驱动程序代码然后将数据包从以太网的设备内存复制到 DMA 缓冲区最后将数据包推送到上层.

If I talk about in layman's term whenever a network packets comes at the interface, it is notified to CPU and appropriate Ethernet driver(interrupt handler) code is executed.Ethernet driver code then copy the packet from Ethernet's Device memory to DMA buffers and finally packets are pushed to upper layer.

以上是否适用于禁用 NAPI 的以太网驱动程序?

Is above true for NAPI disabled Ethernet driver?

现在,对于启用 NAPI 的以太网驱动程序,最初每当数据包到达接口时,它都会通知 CPU 并执行适当的以太网驱动程序代码(中断处理程序).在中断处理程序代码中,我们检查是否收到了中断类型的数据包.

Now for NAPI enabled Ethernet driver initially whenever packets comes at interface ,it is notified to CPU and appropriate Ethernet driver code (Interrupt handler) is executed .Inside the interrupt handler code we check if type of interrupt is received packet.

 if(statusword & SNULL_RX_INTER)
   snull_rx_ints(dev,0);//Disbale further interrupts
   netif_rx_schedule(dev);

禁用更多中断是什么意思?

What does it mean by disabling further interrupts?

这是否意味着数据包仍然被设备捕获并保存在设备内存中,但没有通知 CPU 这些数据包的可用性?

Is it mean packets are still captured by device and kept in device memory but not notified to CPU about the availability of these packets?

另外,CPU 正在池化设备是什么意思,是不是像 CPU 每隔几秒就会运行 snull_poll() 方法并将设备内存中的任何数量的数据包复制到 DMA 缓冲区和推到上层?

Also ,what it mean by CPU is pooling the device ,is it like CPU after every few second will run snull_poll() method and copy whatever number of packets are in device memory to DMA Buffer and pushed to Upper layer?

如果有人给我提供清晰的图片会很有帮助.

It would be great help if someone provides me clear picture on it.

推荐答案

现在,对于启用 NAPI 的以太网驱动程序,最初每当数据包到达接口时,它都会通知 CPU 并执行适当的以太网驱动程序代码(中断处理程序).在中断处理程序代码中,我们检查是否收到了中断类型的数据包.

Now for NAPI enabled Ethernet driver initially whenever packets comes at interface ,it is notified to CPU and appropriate Ethernet driver code (Interrupt handler) is executed .Inside the interrupt handler code we check if type of interrupt is received packet.

禁用更多中断意味着什么?

What it mean by disabling further interrupts?

通常,驱动程序会清除导致中断的条件.但是,当 ISR 完成时,NAPI 驱动程序也可以禁用接收中断.
假设是一个以太网帧的到达可能是一个突发或大量帧的开始.因此,与其退出中断模式并可能立即重新进入中断模式,不如测试(即轮询)是否已经有更多帧到达?

Normally a driver would clear the condition causing the interrupt. The NAPI driver, however, may also disable the receive interrupt when the ISR is done.
The assumption is that the arrival of one Ethernet frame may be the start of a burst or flood of frames. So instead of exiting interrupt mode and likely immediately reentering interrupt mode, why not test (i.e. poll) if more frames have already arrived?

这是否意味着数据包仍然被设备捕获

Is it mean packets are still captured by device

是的.
每个到达的帧都由以太网控制器存储在帧缓冲区中.

Yes.
Each arriving frame is stored by the Ethernet controller in a frame buffer.

并保存在设备内存中

通常不是设备内存".
它通常是分配给以太网控制器的主内存中分配的一组缓冲区(例如环形缓冲区).

It's not typically "device memory".
It is typically a set of buffers (e.g. ring buffer) allocated in main memory assigned to the Ethernet controller.

但没有通知 CPU 这些数据包的可用性?

but not notified to CPU about the availability of these packets?

由于接收中断已禁用,因此不会通知 NAPI 驱动程序此事件.
但由于驱动程序正忙于处理前一帧,因此无论如何无法立即处理中断请求.

Since the receive interrupt has been disabled, the NAPI driver is not notified of this event.
But since the driver is busy processing the previous frame, the interrupt request could not be serviced immediately anyway.

此外,CPU 是池化设备的意思,

Also ,what it mean by CPU is pooling the device ,

想必您实际上是在问轮询"吗?
轮询只是意味着程序(即驱动程序)询问(即读取和测试)状态位以获取它正在等待的条件.
如果满足条件,那么它将以类似于该事件的中断的方式处理该事件.
如果不满足条件,则它可能会循环(在一般情况下).但是,当轮询指示没有更多帧到达时,NAPI 驱动程序将假设数据包突发或泛洪结束,并恢复中断模式.

Presumably you are actually asking about "polling"?
Polling simply means that the program (i.e. the driver) interrogates (i.e. reads and tests) status bit(s) for the condition it is waiting for.
If the condition is met, then it will process the event in a manner similar to an interrupt for that event.
If the condition is not met, then it may loop (in the generic case). But the NAPI driver, when the poll indicates that no more frames have arrived, will assume that the packet burst or flood is over, and will resume interrupt mode.

是否像 CPU 每隔几秒就会运行 snull_poll() 方法并将设备内存中任意数量的数据包复制到 DMA 缓冲区并推送到上层?

is it like CPU after every few second will run snull_poll() method and copy whatever number of packets are in device memory to DMA Buffer and pushed to Upper layer?

NAPI 驱动程序不会在轮询前延迟或暂停自身几秒钟".
假设以太网帧可能会淹没端口,因此一旦对当前帧的处理完成,就会执行轮询.

The NAPI driver would not delay or suspend itself for a "few second"s before polling.
The assumption is that Ethernet frames could be flooding the port, so the poll would be performed as soon as processing on the current frame is complete.

NAPI 驱动程序中可能存在的错误称为腐烂数据包".
当驱动程序从轮询模式转换回中断模式时,帧可能会在此转换期间到达并且不会被驱动程序检测到.
直到另一帧到达(并产生中断),前一帧才会被找到"并由 NAPI 驱动程序处理.

A possible bug in a NAPI driver is called "rotting packet".
When the driver transitions from the poll mode back to interrupt mode, a frame could arrive during this transition and be undetected by the driver.
Not until another frame arrives (and generates an interrupt) would the previous frame be "found" and processed by the NAPI driver.

顺便说一句
您始终如一地编写类似于CPU 所做的……"的陈述或问题;或通知 CPU".
CPU 始终(不休眠或关闭电源时)执行机器指令.
您应该关心这些指令属于哪个逻辑实体(即哪个程序或源代码模块).
您问的是软件问题,因此中断导致 CPU 执行已知的特定序列这一事实是给定的,无需提及.

BTW
You consistently write statements or questions similar to "the CPU does ..." or "notified to CPU".
The CPU is always (when not sleeping or powered off) executing machine instructions.
You should be concerned about to which logical entity (i.e. which program or source code module) those instructions belong.
You're asking software questions, so the fact that an interrupt causes a known, certain sequence by the CPU is a given and need not be mentioned.

附录

我只是想了解 Linux 源代码中的 drivers/net/ethernet/smsc/smsc911x.c.

I am just trying to understand drivers/net/ethernet/smsc/smsc911x.c in Linux source code.

SMSC LAN911x 以太网芯片比我习惯的和上面描述的更复杂.除了 MAC,这些芯片还具有集成的 PHY,并具有 TX 和 RX FIFO,而不是在主存储器中使用缓冲环或列表.

The SMSC LAN911x Ethernet chips are more sophisticated than what I'm used to and have been describing above. Besides the MAC, these chips also have an integrated PHY, and have TX and RX FIFOs instead of using buffer ring or lists in main memory.

根据您的建议,我已开始阅读 SMSCLan9118 数据表并尝试将其映射到 smsc911x_irqhandler 函数,其中中断状态 (INT_STS) 和中断启用 (INT_EN) 寄存器已被读取但不知道如何
if (likely(intsts & inten & INT_STS_RSFL_))
此处在第 1627 行检查条件.

As per your suggestion I have started reading the SMSCLan9118 datasheet and trying to map it with smsc911x_irqhandler function where interrupt status (INT_STS) and interrupt enable (INT_EN) registers have been read but don't get how
if (likely(intsts & inten & INT_STS_RSFL_))
condition is checked here in line 1627.

INT_STS 在头文件中定义为

INT_STS is defined in the header file as

#define INT_STS                         0x58

以及数据表中第 5.3 节系统控制和状态寄存器"中的表格将(相对)地址 0x58 处的寄存器列为

and the table in Section 5.3, System Control and Status Registers, in the datasheet lists the register at (relative) address 0x58 as

58h INT_STS Interrupt Status 

因此 smsc911x 设备驱动程序使用与硬件数据表完全相同的寄存器名称.
使用 ISR 中的此寄存器偏移量读取此 32 位寄存器:

So the smsc911x device driver uses the exact same register name as the HW datasheet.
This 32-bit register is read using this register offset in the ISR using:

u32 intsts = smsc911x_reg_read(pdata, INT_STS);

因此,中断状态的 32 位(在变量 intsts 中)与中断掩码的 32 位(在变量 inten 中)进行布尔与运算.
这会产生驱动程序实际感兴趣的中断状态位.这也可能是很好的防御性编程,以防硬件为尚未启用的中断条件设置状态位(在 INT_EN 寄存器中).
然后该 if 语句执行另一个布尔 AND 来提取正在检查的一位 (INT_STS_RSFL_).

So the 32 bits of the interrupt status (in variable intsts) is Boolean ANDed with the 32 bits of the interrupt mask (in variable inten).
This produces the interrupt status bits that the driver are actually interested in. This may also be good defensive programming in case the HW sets status bits anyway for interrupt conditions that have not been enabled (in the INT_EN register).
Then that if statement does another Boolean AND to extract the one bit (INT_STS_RSFL_) that is being checked.

5.3.3 INT_STS—Interrupt Status Register

RX Status FIFO Level Interrupt (RSFL).
Generated when the RX Status FIFO reaches the programmed level

likely() 运算符用于编译器优化以利用 CPU 中的分支预测功能.驱动程序的作者正在指示编译器优化代码以获得所包含的逻辑表达式的真实结果(例如三个整数的 AND 运算,这将指示需要服务的中断条件).

The likely() operator is for compiler optimization to utilize branch prediction capabilities in the CPU. The driver's author is directing the compiler to optimize the code for a true result of the enclosed logic expression (e.g. the ANDing of three integers, which would indicate an interrupt condition that needs servicing).

还有关于在哪个寄存器上设置了哪个位的接口上接收数据包.

Also on recieving the packet on interface which bit is set on which register.

我对 LAN9118 数据表的看法是,确实没有专门用于接收帧的中断.
相反,可以在 RX FIFO 超过阈值时通知主机.

My take on reading the LAN9118 datasheet is that there really is no interrupt specifically for the receipt of a frame.
Instead the host can be notified when the RX FIFO exceeds a threshold.

5.3.6 FIFO_INT—FIFO Level Interrupts

RX Status Level.
The value in this field sets the level, in number of DWORDs, at which the RX Status FIFO Level interrupt (RSFL) will be generated. 
When the RX Status FIFO used space is greater than this value an RX Status FIFO Level interrupt (RSFL) will be generated. 

smsc911x 驱动程序显然在其默认值为零时使用此阈值.
RX 状态 FIFO 中的每个条目都占用一个 DWORD.该阈值的默认值为 0x00(即第一"帧上的中断).如果该阈值大于零,则存在腐烂数据包"的可能性.

The smsc911x driver apparently uses this threshold at its default value of zero.
Each entry in the RX Status FIFO occupies a DWORD. The default value of this threshold is 0x00 (i.e. interrupt on "first" frame). If this threshold is more than zero, then there is the possibility of "rotting packets".

这篇关于关于 Linux 内核中的 NAPI 实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆