noNAPI:
MAC每收到一个包或者BD即产生一个中断,缺点是网络PPS高时,CPU将大部分时间耗费在了MAC中断上。
netpoll:
NAPI:
NAPI实现原理
在网络驱动中使用NAPI提升效率,核心概念是不使用中断的方式读取数据,而是以中断唤醒数据接收服务程序,然后以POLL的方法来轮询数据。即在收到中断后,调用dev->poll方法,关闭中断。这样,随着接收速度增加,中断能做到不断减少。通过这种方式能够大大改善短包接收的效率,因为不需要每个小报文或者报文的一部分就触发一次中断处理过程。
缺陷是如果上层应用处理较慢,内核累计的数据包会消耗大量内存,另外对于大包没有明显改善。轮询收包处理方法为process_backlog,是一个循环接收操作。
1.
2.
NAPI常用接口:
注册NAPI举例:
具体实现原理
需要实现的代码
中断上半部中
1.
2.
3.
中断下半部中:
1.
2.
3.
4.
5.
某项目的NAPI实现:
1)
在驱动初始化xx_netdev_init()
{
注册设备,并添加为napi设备
dummy_dev = alloc_etherdev(0);
init_dummy_netdev(dummy_dev); // do i have toregister?
netif_napi_add(dummy_dev, &global_napi,rxqueue_napi_poll, prm_weight);
napi_enable(&global_napi);
打开收包中断
}
2)
static inline intnetdev_read_packet(void)
{
从硬件queue中收包放入skb,
判断收到包的协议包类型,调用相应回调
}
static intrxqueue_napi_poll(struct napi_struct *napi, int budget)
{
在单次收包数(budget)的数量内:
持续调用netdev_read_packet()收包,直到budget用完或者queue为空。
如果是因为包收完退出循环:
}
3)
static voidrxqueue_isr(BL_CPU_RX_QUEUE_ID_DTE queue_id)
{
关收包中断,然后开启NAPI轮询
}
我所调试过的几个网口驱动:
为什么说是调试过的几个驱动,意思很明显,就是程序不是我的原创,咱只是来porting或者修BUG的。悲剧….
1.
这个就是中断驱动的收包方式。
接收时,所有BD设置中断,64个BD组成一个RING。收到中断后,关闭中断,循环收包,但是不关闭接收,形成软件取报文,填充BD EMPYTY状态与DMA同时工作的场景。直到收空完BD后,打开中断。
发送时设置BD表,每个包的最后一个BD触发中断,以便释放sk_buffer中的内存,以及从RING中删除掉已经接收的BD。
2.
中断中发送event,然后迅速退出
启动一个等待event的高优先级任务,使用FIFO调度方式,进入一个等待event的循环
处理报文过程中,多个event会产生合并。但不会出现所有event都丢失的情况。
3.
声明tasklet
启动硬件timer,时间很短,小于1ms,防止收发包时延太大
timer回调中启动tasklet
tasklet的回调中,循环收包,直到把包给收空