One concrete usage can be :
echo 20000 >/sys/class/net/eth1/gro_flush_timeout
echo 10 >/sys/class/net/eth1/napi_defer_hard_irqs
If at least one packet is retired, then we will reset napi counter
to 10 (napi_defer_hard_irqs), ensuring at least 10 periodic scans
of the queue.
On busy queues, this should avoid NIC hard IRQ, while before this patch IRQ
avoidance was only possible if napi->poll() was exhausting its budget
and not call napi_complete_done().
通过套入式的方法来理解这两个参数,先有个概念
Q1: NAPI分别是什么用来作甚
A1: NAPI 接收数据包的方式和传统方式不同,它允许设备驱动注册一个 poll 方法,然后调 用这个方法完成收包。大概过程是这样的,网卡接受到一个包,DMA搬运到内存,触发一个中断,然后伴随soft irq,唤醒NAPI接管合并调用驱动的poll 方法收包,并抑制网卡的硬件中断,当没有包接受了,唤醒网卡硬件中断。
和传统的硬件中断收包相比,NAPI一次可以收多个包,从而提高收包效率,降低中断频率。
通过netif_napi_add 函数注册NAPI
Q2: GRO分别是什么用来作甚
A2: GRO(Generic Receive Offload)的功能将多个 TCP 数据聚合在一个skb(socbuff)结构,然后作为一个大数据包交付给上层的网络协议栈,以减少上层协议栈处理skb的开销,提高系统接收TCP数据包的性能。这个功能需要网卡驱动程序的支持。合并了多个skb的超级 skb能够一次性通过网络协议栈,从而减轻CPU负载。
GRO是针对网络收包流程进行改进的,并且只有NAPI类型的驱动才支持此功能。因此如果要支持GRO,不仅要内核支持,驱动也必须调用相应的接口来开启此功能。用ethtool -K gro on来开启GRO。
GRO与TSO类似,但TSO只支持发送数据包。支持GRO的驱动会在NAPI的回调poll方法中读取数据包,然后调用GRO的接口napi_gro_receive或者napi_gro_frags来将数据包送进协议栈。
例如virtionet中函数调用栈如下
receive_buf->napi_gro_receive->skb_gro_reset_offset->napi_skb_finish