分享
 
 
 

FreeBSD 浅谈watchdog timeout出现的原因

王朝system·作者佚名  2006-11-23
窄屏简体版  字體: |||超大  

最近有比较多的人谈到网卡的”watchdog timeout“问题,究竟是什么原因造成的,大多数人都

把网卡的性能不佳做为问题的根源所在。我认为网卡的性能只是一方面的因素,他还涉及到缓冲的

大小、单位时间内的包的数量、及网卡驱动程序等一系列因素。以下将从源代码的角度来对他进行

分析。

首先,我们看看到底是哪个函数发出了“watchdog timeout”字符串,只要你查一下源代码

不难看出,在各网卡的驱动程序里的XX_watchdog(XX是各网卡的名称,如:8139是rl,AMD7990

是pcn,Inter是fxp等等)函数发出的。函数比较简单:

static void rl_watchdog(ifp)

struct ifnet *ifp;/*申明ifp是一个ifnet结构,结构存放了该网卡的输入输

出的函数指针和一些重要参数,当然也包括rl_watchdog函数的

指针*/

{

struct rl_softc *sc;

sc = ifp->if_softc; /*ifnet是softc结构的一个子集,softc包含了更多的该网卡的参数*/

printf("rl%d: watchdog timeout\n", sc->rl_unit);/*打印出是哪块网卡出现问题。

sc->rl_unit代办该种网卡的第几快。我们知道在一个机器里同样

的网卡可能有几块,当然此参数是由网卡驱动程序的初始化程序填充*/

ifp->if_oerrors++; /*累计输出出现的错误包数量(o代表输出)*/

rl_txeof(sc);/*这里是每个驱动程序不同的,此处为8139的,不过我觉得用rl_stop(sc)更好*/

rl_rxeof(sc);/*这里也是每个驱动程序不同。我觉得来一个rl_reset(sc)也不错。*/

rl_init(sc);/*这里大家都一样,重新初始芯片。*/

return;

}

好了,到这我们知道是XX_watchdog函数发出了watchdog timeout信息。那么是谁来调用该函数呢?

我们接着来看另一个函数:if_slowtimo函数,该函数在if.c中。if.c是interface(接口)的简称,

即系统在启动过程中初始化时必须调用其中的一些函数。ifinit函数是其中被调用的一个,这个函数很

简单:

void

ifinit()

{

static struct timeout if_slowtim;

timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);/*简单的说就是设置一定时器*/

if_slowtimo(&if_slowtim);/*哈哈,等不急了,先调用了再说*/

}

这样一来,if_slowtimo就成了一个一定时间内就要执行的一个函数了,此时候,大家应该能猜到if_slowtimo

的大概功能,无非是定时查看各网卡的发送数据的情况,如果没发送完成,就给该卡加一个计数器,到

计数器达到一定的值时还没发送出去就调用该卡的XX_watchdog函数。下面我们来看看if_slowtimo函数。

void

if_slowtimo(arg)

void *arg;

{

struct timeout *to = (struct timeout *)arg;

struct ifnet *ifp;

int s = splimp();/*在做以下操作的时候必须关中断*/

TAILQ_FOREACH(ifp, &ifnet, if_list) {/*搜索每一个接口设备,TAILQ_FOREACH实际上是for(...)*/

if (ifp->if_timer == 0 || --ifp->if_timer)

continue;/*如果是if_timer为0或if_timer减1以后还为真,实际上是对每块网卡

的计数器if_timer减1后判断他是否还大于0,小于0就调用watchdog函数。*/

if (ifp->if_watchdog) /*不过调用之前看看该卡有没有watchdog函数*/

(*ifp->if_watchdog)(ifp);

}

splx(s);

timeout_add(to, hz / IFNET_SLOWHZ);/*每次计时器完成后都会清除,你不得不又加上去。hz是计算

机的主频,就是说调度的间隔时间是和主频成正比的关系。*/

}

到这里一切都很明白了,我们只要在驱动程序的输出包时给定一个值(if_timer,大多数是5),而输出函数是一个

直到输出成功才跳出的循环,不成功他就一直重试来输出此包,而我们上面的程序就会时间一到就给你的值减1,如果

减到小于0了,就watchdog timeout。我们还是来看一看程序吧:

static void rl_start(ifp)

struct ifnet *ifp;

{

struct rl_softc *sc;

struct mbuf *m_head = NULL;

sc = ifp->if_softc;

while(RL_CUR_TXMBUF(sc) == NULL) {/* 1:当输出缓冲区为空时才进行新的输出*/

IF_DEQUEUE(&ifp->if_snd, m_head);/*把将要输出的数据加入到输出队列中。*/

if (m_head == NULL)/* 2:申请内存失败*/

break;

if (rl_encap(sc, m_head)) {/*8139卡的弱智表现在此,多加一个头部,还要长字节对齐,影响

到数据必须重新搬迁。花时间啊!*/

IF_PREPEND(&ifp->if_snd, m_head);

ifp->if_flags |= IFF_OACTIVE;

break;

}

if (ifp->if_bpf)/* 3:如果包过滤存在就进行过滤*/

bpf_mtap(ifp, RL_CUR_TXMBUF(sc));

CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),/* 4:以下为硬件输出的IO指令*/

vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));

CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),

RL_TXTHRESH(sc->rl_txthresh) |

RL_CUR_TXMBUF(sc)->m_pkthdr.len);

RL_INC(sc->rl_cdata.cur_tx);

}

if (RL_CUR_TXMBUF(sc) != NULL)/*如果传送缓冲不为空,说明数据放到缓冲中已经准备传了*/

ifp->if_flags |= IFF_OACTIVE;/*加上正在传标志*/

ifp->if_timer = 5;/*设定计数器为5*/

return;

}

大家注意看我注释中的1,2,3,4标号,即是4个有可能使传送出现问题的地方。但大家也会问:即使我传送

成功了也会if_timer变成5啊,那么成功了后是怎么消除这个5的呢,答案在当传送完一个包后,网卡将产生一个

中断,我们来看中断程序:

static void rl_intr(arg)

{

... 这中间我就不写了

if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR)) /*如果中断后状态寄存器的标识

是成功或出错,就调用下面的程序。*/

rl_txeof(sc);

...

}

再看rl_txeof:

static void rl_txeof(sc)

{

...

ifp->if_timer = 0;/*哈哈,在这清0了,也就是说,只要你不是反复在那传,不过错误和传输正确

都不会出现"watchdog timeout"*/

...

}

综上所述:引起watchdog timeout的主要原因为:1、缓冲区不够大,前面的没发完后面的又跟的来了。2、内核

的内存分配出现问题,此情况比较少发生。3、卡的质量(在IO时的吞吐量)。4、bpf过滤过于复杂引起。

如何解决这个问题:

首先我们必须查出导致出现该问题的原因,即是4个问题中的哪个引起的,我们来修改驱动程序和相关的程序:

在if.h中定义一全局变量:

u_int8_t myerror; /*意思是出错的原因代码,按我列的来吧,1是缓冲区不够...*/

在函数static void rl_start(ifp)中加入:

static void rl_start(ifp)

struct ifnet *ifp;

{

struct rl_softc *sc;

struct mbuf *m_head = NULL;

sc = ifp->if_softc;

u_int8_t tmperror;

if (RL_CUR_TXMBUF(sc) != NULL) {/*新加,如果是缓冲区不够问题*/

myerror=1;

}

while(RL_CUR_TXMBUF(sc) == NULL) {

IF_DEQUEUE(&ifp->if_snd, m_head);

if (m_head == NULL)

{

myerror=2; /*内存分配出错*/

break;

}

if (rl_encap(sc, m_head)) {

IF_PREPEND(&ifp->if_snd, m_head);

ifp->if_flags |= IFF_OACTIVE;

break;

}

if (ifp->if_bpf)

bpf_mtap(ifp, RL_CUR_TXMBUF(sc));

tmperror=myerror;/*在进行写IO口前先保存前面出错的原因*/

CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),

vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));

CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),

RL_TXTHRESH(sc->rl_txthresh) |

RL_CUR_TXMBUF(sc)->m_pkthdr.len);

myerror=tmperror;/*上面两句没问题的话再还原前面的出错原因*/

RL_INC(sc->rl_cdata.cur_tx);

}

if (RL_CUR_TXMBUF(sc) != NULL)

ifp->if_flags |= IFF_OACTIVE;

ifp->if_timer = 5;

return;

}

最后再改一下rl_watchdog中的显示部分

printf("rl%d: watchdog timeout:error number is %x\n", sc->rl_unit,myerror);

当然这只是我个人的见解,可能有许多不足或没考虑到的地方,也希望大家能提出更好、更容易

的方法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有