Chinaunix首页 | 论坛 | 博客
  • 博客访问: 477597
  • 博文数量: 63
  • 博客积分: 1485
  • 博客等级: 上尉
  • 技术积分: 596
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-21 14:49
文章分类

全部博文(63)

文章存档

2018年(8)

2017年(25)

2016年(10)

2012年(6)

2010年(14)

我的朋友

分类: LINUX

2012-07-12 16:02:07

 snull.rar   

把LDD3中snull的代码拿来发现在linux 2.6.29.4下编译不能通过,看了看出错信息,应当是linux版本的问题;在网上找了一个修改并能通过编译的snull版本,果然可以编译通过。

运行后发现:
不设置use_napi, lockup,timeout的情况下,可以正常工作;
但是如果设置了use_napi或者设置了lockup和timeout,就不能正常工作了。

以下是问题的解决。修改后的代码在附件中。

1、use_napi下的问题

首先看了看use_napi的模式下,napi_complete和napi_schedule的用法没有问题,netif_napi_add也正常添加了,可是为什么ping不通呢?

看了看napi_complete和napi_schedule的实现,都有对NAPI_STATE_SCHED这个标记位的检查;这两个比较高层的函数在调用底层实现之前,会判断这些标记,以保证系统设置是正确的逻辑。

static inline void napi_schedule(struct napi_struct *n)
{
    if (napi_schedule_prep(n))
        __napi_schedule(n);
}
napi_schedule_prep判断了NAPI_STATE_SCHED,如果该标记有被置位,那么返回0,也就是说,这种情况下__napi_schedule不能被执行。另外,无论如何,在napi_schedule_prep中,都会把NAPI_STATE_SCHED进行置位。

napi_complete->__napi_complete,这里首先判断NAPI_STATE_SCHED,如果没有置位,那么调用BUG_ON;否则继续执行;在这个函数最后,清掉NAPI_STATE_SCHED标记。

对于接收函数的处理模型来说,在napi模式下,如果得到rx中断,那么首先关闭rx中断,然后调用napi_schedule;这样接下来注册过的poll函数就会被调用到。在poll结束的时候,调用napi_complete,然后开启rx中断。

根据上面的逻辑来看,应当是这样:
进入到napi_schedule之前,NAPI_STATE_SCHED必须被清掉;接下来,进入到napi_schedule中,置位NAPI_STATE_SCHED;然后在napi_complete中把该位清掉。当下一个rx中断到来的时候,再次进入napi_shedule中,形成一个循环。

再看看netif_napi_add的实现,对NAPI_STATE_SCHED标记进行了置位。
哦,这样的话,首次进入napi_shecdule的条件就不符合了,所以需要在首次进入napi_shedule之前清掉NAPI_STATE_SCHED置位。

非常简单的做法,在netif_napi_add之后,紧接着调用一次napi_complete。
OK,NAPI_STATE_SCHED标记位符合正常操作的逻辑了。

个人对这个修改不是很满意,大家有好的解决办法,请更正!



2、lockup/timeout的问题

在没有配置use_napi的情况下,设置了lockup/timeout的值,假设都是5吧。发现系统也不能工作(ping不通)。系统会抛出异常,表示在tx方向获取buffer失败。
这种工作模式的配置下,模拟了以下的工作场景:
如果连续发了lockup个报文,那么假装系统出现问题,手动把tx queue停掉。这样系统就会等到timeout,然后去处理问题,再把tx queue唤醒。
那为什么出现问题呢,分析后发现,网上修改过的代码,忘记赋值timeout了(网上的代码根据新的内核结构对net_device进行了初始化,连同timeout也注掉了)。

解决很简单,对timeout进行赋值即可。





阅读(4111) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

arm_zwinger2012-07-18 15:53:04

这两天看了下网卡驱动,又有点新的认识。

在上面描述的第一个问题里,我最后是在netif_napi_add之后直接调用了napi_complete来清掉标志。

现在知道了,直接在netif_napi_add之后适时地调用napi_enable即可,它仅仅包好了清掉标志的功能。

修改后,编译,通过测试!