- 論壇徽章:
- 13
|
早起捉到一只8139驅(qū)動的bug。
先說一下測試的環(huán)境,是一根網(wǎng)線連著linux機(jī)器(也就是我寫程序的)和裝有papaya內(nèi)核的機(jī)器(下面簡稱papaya機(jī)器)。
是在測試tcp的時候,內(nèi)核收到第一次tcp syn,沒有響應(yīng)。
但當(dāng)這個syn重發(fā)到內(nèi)核(netcat會自動重發(fā)的),也就是內(nèi)核第二次收到這個syn,就響應(yīng)了。
而且是響應(yīng)兩次:它ack了`第一次的tcp syn,并且忽略了第二次的syn(內(nèi)核當(dāng)然該這么做)。
我發(fā)現(xiàn),如果我手速快的話,在netcat向內(nèi)核重發(fā)tcp syn 之前,ctrl-C掉它,也就是不讓內(nèi)核接受到第二次tcp syn。
然后,我ping一下ppaaya機(jī)器,這時輸出較少,很清楚的看到,內(nèi)核被第一個icmp包中斷后,驅(qū)動在一個收包中斷里讀出了兩個包。第一個包就是tcp syn。
這樣就把bug定位到了8139的驅(qū)動,它為什么沒能讀出早先的那個syn包?而是讓它停在網(wǎng)卡上?
這時,我留意到,屏幕上打印的與網(wǎng)卡中斷相關(guān)的信息,是以發(fā)包(Tx)中斷結(jié)束的,在Tx中斷之后,網(wǎng)卡就“沉默”了,它本來還應(yīng)該有一次Rx中斷。
于是想到了,可能這次Rx中斷發(fā)生在Tx中斷的routine里,但是Tx的routine把8139的ISR寄存器整個清零了。包括ROK位。
那,等從這次Tx中斷出去,期間的這次Rx中斷也就丟了。
都是因?yàn)檫@句代碼:
RTL_writew(netdev, ISR, 0xffff);
改成:
RTL_writew(netdev, ISR, TxOK);
就好了。只清除ISR上TxOK這個bit。
其實(shí)這個bug只是偶爾出現(xiàn): 在papaya機(jī)器啟動之前,我不把linux機(jī)器的ip配置成192.168.0.22, 它才會出現(xiàn)。
為什么是這樣呢:
papaya內(nèi)核在啟動的時候,默認(rèn)會向192.168.0.22(linux機(jī)器)發(fā)送一個ARP詢問。一旦把linux的ip修改掉,那這次開機(jī)詢問就無功而返(其實(shí)是無功無返)。
于是,當(dāng)linux機(jī)器向192.168.0.9(papaya機(jī)器)發(fā)送tcp syn包時,它不得不先做一次ARP詢問,獲取相應(yīng)的mac。
我們從papaya機(jī)器的角度看:
(收包)收到ARP inquiry ====> (發(fā)包)發(fā)送ARP reply ====> (收包)收到TCP syn
發(fā)送ARP reply之后,很快網(wǎng)卡產(chǎn)生Tx中斷。 而linux收到了這個arp reply,會立刻把syn包發(fā)過來,因?yàn)榫W(wǎng)線很短,在Tx的中斷例程里,這個syn包就過來了。然后就。。。
如果在papaya機(jī)器開機(jī)時的ARP詢問成功了呢?
那linux機(jī)器發(fā)送tcp syn包之前,就不需要再做一次ARP詢問,也就沒有接下來的事情了。
這個bug只在收發(fā)包密集交錯的時候才會出現(xiàn)。
到現(xiàn)在我似乎又明白了一個問題,之前經(jīng)常出現(xiàn)的spurious irq;或者陷入網(wǎng)卡中斷后,驅(qū)動卻發(fā)現(xiàn)ISR是0 ?赡芏几@個bug有關(guān)。
PS:
只在具體的中斷分支里清除ISR上相應(yīng)的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循環(huán),它應(yīng)該是試圖處理在這次中斷例程里又發(fā)生的中斷。
另一方面,linux很早的就一次性清除了ISR的所有位, 這樣就ISR就可以盡快的indicate接下來的中斷。
這是兩個很常規(guī)的提升性能的舉措。附: linux2.038內(nèi)核里的rtl8139.c ,自己改一下后綴。
rtl8139.zip
(43.69 KB, 下載次數(shù): 15)
2016-07-19 11:07 上傳
點(diǎn)擊文件名下載附件
|
評分
-
查看全部評分
|