常用的网络驱动收包方式

noNAPI:      

MAC每收到一个包或者BD即产生一个中断,缺点是网络PPS高时,CPU将大部分时间耗费在了MAC中断上。

netpoll:

      轮询收包,实时性差。

NAPI:

      中断+轮询方式,MAC收到第一个包时产生中断,收包程序中关闭该中断,启动轮询收包,知道收完buffer中的所有包或者是netdev_max_backlog个包之后,重新打开中断。Sysctl或者proc可以修改netdev_max_backlog的数值。

 

NAPI实现原理

在网络驱动中使用NAPI提升效率,核心概念是不使用中断的方式读取数据,而是以中断唤醒数据接收服务程序,然后以POLL的方法来轮询数据。即在收到中断后,调用dev->poll方法,关闭中断。这样,随着接收速度增加,中断能做到不断减少。通过这种方式能够大大改善短包接收的效率,因为不需要每个小报文或者报文的一部分就触发一次中断处理过程。

缺陷是如果上层应用处理较慢,内核累计的数据包会消耗大量内存,另外对于大包没有明显改善。轮询收包处理方法为process_backlog,是一个循环接收操作。

 

      使用NAPI依赖于:

1. 使用DMA或者有足够内存缓存收到的包

2. TX/RX时,能关闭中断,并且中断的关闭不影响硬件DMA收包操作

 

NAPI常用接口:

      napi_complete/napi_schedule/netif_napi_add/napi_enable

 

注册NAPI举例:

       dummy_dev = alloc_etherdev(0);

       init_dummy_netdev(dummy_dev); // do i have to register?

       netif_napi_add(dummy_dev, &global_napi,rxqueue_napi_poll, prm_weight);

       

       napi_enable(&global_napi);

 

具体实现原理

      每个net_device中都有一个napi_struct数据结构,到收到数据包时驱动将自己的napi_struct挂到poll_list上,然后在软中断中net_rx_action会遍历该数据结构上挂的所有napi_struct结构的poll钩子函数,将数据包从硬件中收到协议栈数据结构中。

      Poll_list是基于CPU的变量。使用的softirq的标号为NET_TX_SOFTIRQNETRX_SOFTIRQ两个软中断号。

 

需要实现的代码

中断上半部中

1. 关中断,设置napi_struct.stateNAPI_STATE_SCHED

2. 将自己的napi_struct挂载到_get_cpu_var(softnet_data).poll_list

3. 触发收包软中断

中断下半部中:

1. 执行网络接收软中断handlernet_rx_action

2. 遍历_get_cpu_var(softnet_data).poll_list

3. 取出poll_list上面挂的napi_struct结构,执行napi_struct.poll()

4. 如果poll函数中收完所有的包,打开中断

5. 调用napi_complete(napi_struct *n)napi_structpoll_list上移走并修改NAPI_STATE_SCHED状态

 

某项目的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为空。

 

如果是因为包收完退出循环:

      调用napi_complete()napi_struct挪出poll_list,重新打开收包中断

}

 

3)       收包中断回调

static voidrxqueue_isr(BL_CPU_RX_QUEUE_ID_DTE queue_id)

{

关收包中断,然后开启NAPI轮询

   napi_schedule(&global_napi);

}

 

我所调试过的几个网口驱动:

为什么说是调试过的几个驱动,意思很明显,就是程序不是我的原创,咱只是来porting或者修BUG的。悲剧….

1.      PPC处理器,自己开发的TSEC网口驱动

这个就是中断驱动的收包方式。

接收时,所有BD设置中断,64BD组成一个RING。收到中断后,关闭中断,循环收包,但是不关闭接收,形成软件取报文,填充BD EMPYTY状态与DMA同时工作的场景。直到收空完BD后,打开中断。

 

发送时设置BD表,每个包的最后一个BD触发中断,以便释放sk_buffer中的内存,以及从RING中删除掉已经接收的BD

 

2.      网络处理器到CPU收发包网口驱动

中断中发送event,然后迅速退出

启动一个等待event的高优先级任务,使用FIFO调度方式,进入一个等待event的循环

       收到event后,循环接收完queue内的所有报文,这个过程中硬件收包不关闭

       接收x个包后退出一次loop,防止系统软件狗超时

处理报文过程中,多个event会产生合并。但不会出现所有event都丢失的情况。

3.      POLL方式收包

声明tasklet

启动硬件timer,时间很短,小于1ms,防止收发包时延太大

timer回调中启动tasklet

tasklet的回调中,循环收包,直到把包给收空


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值