免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1486 | 回复: 3
打印 上一主题 下一主题

[内核入门] 早起捉到一只8139驱动的bug [复制链接]

论坛徽章:
13
程序设计版块每日发帖之星
日期:2016-06-29 06:20:00每日论坛发贴之星
日期:2016-08-14 06:20:00操作系统版块每日发帖之星
日期:2016-08-14 06:20:00每日论坛发贴之星
日期:2016-08-13 06:20:00数据库技术版块每日发帖之星
日期:2016-08-13 06:20:00程序设计版块每日发帖之星
日期:2016-08-13 06:20:00IT运维版块每日发帖之星
日期:2016-08-13 06:20:00每日论坛发贴之星
日期:2016-08-12 06:20:00数据库技术版块每日发帖之星
日期:2016-08-12 06:20:00程序设计版块每日发帖之星
日期:2016-08-12 06:20:00操作系统版块每日发帖之星
日期:2016-08-12 06:20:00综合交流区版块每日发帖之星
日期:2016-08-09 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-19 11:08 |只看该作者 |倒序浏览
早起捉到一只8139驱动的bug。
  先说一下测试的环境,是一根网线连着linux机器(也就是我写程序的)和装有papaya内核的机器(下面简称papaya机器)。

  是在测试tcp的时候,内核收到第一次tcp syn,没有响应。
  但当这个syn重发到内核(netcat会自动重发的),也就是内核第二次收到这个syn,就响应了。
  而且是响应两次:它ack了`第一次的tcp syn,并且忽略了第二次的syn(内核当然该这么做)。

  我发现,如果我手速快的话,在netcat向内核重发tcp syn 之前,ctrl-C掉它,也就是不让内核接受到第二次tcp syn。
  然后,我ping一下ppaaya机器,这时输出较少,很清楚的看到,内核被第一个icmp包中断后,驱动在一个收包中断里读出了两个包。第一个包就是tcp syn。

  这样就把bug定位到了8139的驱动,它为什么没能读出早先的那个syn包?而是让它停在网卡上?
  这时,我留意到,屏幕上打印的与网卡中断相关的信息,是以发包(Tx)中断结束的,在Tx中断之后,网卡就“沉默”了,它本来还应该有一次Rx中断。
  于是想到了,可能这次Rx中断发生在Tx中断的routine里,但是Tx的routine把8139的ISR寄存器整个清零了。包括ROK位。
  那,等从这次Tx中断出去,期间的这次Rx中断也就丢了。

  都是因为这句代码:
  RTL_writew(netdev, ISR, 0xffff);
  改成:
  RTL_writew(netdev, ISR, TxOK);
  就好了。只清除ISR上TxOK这个bit。

   其实这个bug只是偶尔出现: 在papaya机器启动之前,我不把linux机器的ip配置成192.168.0.22, 它才会出现。
   为什么是这样呢:
   papaya内核在启动的时候,默认会向192.168.0.22(linux机器)发送一个ARP询问。一旦把linux的ip修改掉,那这次开机询问就无功而返(其实是无功无返)。
  于是,当linux机器向192.168.0.9(papaya机器)发送tcp syn包时,它不得不先做一次ARP询问,获取相应的mac。
  我们从papaya机器的角度看:
  (收包)收到ARP inquiry  ====>   (发包)发送ARP reply ====>  (收包)收到TCP syn
  发送ARP reply之后,很快网卡产生Tx中断。 而linux收到了这个arp reply,会立刻把syn包发过来,因为网线很短,在Tx的中断例程里,这个syn包就过来了。然后就。。。

  如果在papaya机器开机时的ARP询问成功了呢?
  那linux机器发送tcp syn包之前,就不需要再做一次ARP询问,也就没有接下来的事情了。
  这个bug只在收发包密集交错的时候才会出现。

  到现在我似乎又明白了一个问题,之前经常出现的spurious irq;或者陷入网卡中断后,驱动却发现ISR是0 。可能都跟这个bug有关。

PS:
  只在具体的中断分支里清除ISR上相应的bit,是可以解决这个bug。但linux的做法更好,它基本像这样:
  int isr = RTL_readw(netdev, ISR);
  RTL_writew(netdev, ISR, 0xfffff);
  if(isr & RxOK) ...
  if(isr & RxErr) ...
  if(isr & TxOK) ...
  ...
  注意,上面是一系列的if,而不是if, else if, else if .. else。
  linux是在一次中断里,处理ISR上indicate的所有中断。而且在更外围,是一个while循环,它应该是试图处理在这次中断例程里又发生的中断。
  另一方面,linux很早的就一次性清除了ISR的所有位, 这样就ISR就可以尽快的indicate接下来的中断。
  这是两个很常规的提升性能的举措。附: linux2.038内核里的rtl8139.c ,自己改一下后缀。 rtl8139.zip (43.69 KB, 下载次数: 15)

评分

参与人数 1可用积分 +6 收起 理由
Godbach + 6 赞一个!

查看全部评分

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
2 [报告]
发表于 2016-07-19 12:23 |只看该作者
回复 1# karma303

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
3 [报告]
发表于 2016-07-19 15:22 |只看该作者
linux的模型是所有中断共享一个中断处理函数。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
4 [报告]
发表于 2016-07-19 18:57 |只看该作者
回复 1# karma303

赞! 感谢分享。

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP