驅(qū)動(dòng)調(diào)試:從MAC-PHY鏈路到工業(yè)協(xié)議優(yōu)化)
干過(guò)嵌入式驅(qū)動(dòng)的人都有個(gè)共同體驗(yàn)?zāi)玫揭粔K新板子最先想干的事就是讓網(wǎng)口亮起來(lái)。燈亮了串口能進(jìn)shellping通上位機(jī)這塊板子才算活了。反過(guò)來(lái)說(shuō)如果燈不亮、link up不上或者在end用戶態(tài)怎么都收不到包排查起來(lái)往往比點(diǎn)燈復(fù)雜得多——因?yàn)橐蕴W(wǎng)驅(qū)動(dòng)從來(lái)不是一個(gè)驅(qū)動(dòng)而是一條鏈路控制器MAC、物理層芯片PHY、MDIO總線、設(shè)備樹/PCI枚舉、內(nèi)核協(xié)議棧任何一個(gè)環(huán)節(jié)掉鏈子表現(xiàn)就是網(wǎng)口有脾氣。這一期是嵌入式驅(qū)動(dòng)開發(fā)經(jīng)驗(yàn)系列的第10期主題是Ethernet以太網(wǎng)。我把這幾年在嵌入式Linux平臺(tái)上碰到的網(wǎng)口問(wèn)題和處理思路理了一遍重點(diǎn)圍繞幾個(gè)高頻關(guān)鍵詞展開Intel I219-V這類板載千兆控制器的適配、VLAN配置、1G/2.5G PCS/PMA與SGMII這些MAC與PHY之間的鏈路細(xì)節(jié)以及面向EtherNet/IP等工業(yè)協(xié)議場(chǎng)景時(shí)底層驅(qū)動(dòng)該做什么樣的取舍。內(nèi)容不一定高深但都是能直接拿去排查問(wèn)題的思路。1. 一塊新板子來(lái)了先搞清楚網(wǎng)口這條鏈路上誰(shuí)在干活1.1 MAC、PHY與MII總線驅(qū)動(dòng)開發(fā)眼里的一條鏈很多新手拿到網(wǎng)口問(wèn)題第一反應(yīng)是查驅(qū)動(dòng)但驅(qū)動(dòng)這兩個(gè)字在以太網(wǎng)場(chǎng)景里至少包含三層MAC控制器驅(qū)動(dòng)、PHY芯片驅(qū)動(dòng)、以及把兩者連起來(lái)的MII總線管理機(jī)制。這三個(gè)角色各管一段缺一不可。MAC是主控側(cè)的核心它負(fù)責(zé)把內(nèi)存里DMA ring上的數(shù)據(jù)包搬運(yùn)到線路接口上同時(shí)處理幀的填充、CRC校驗(yàn)、流控等底層邏輯。在嵌入式SoC里MAC通常已經(jīng)是片上資源比如Zynq、i.MX、RK系列都有自己的GEM/MAC外設(shè)。而PHY是芯片外部那個(gè)小顆粒負(fù)責(zé)把MAC送出來(lái)的數(shù)字比特流變成物理線纜上的電平信號(hào)同時(shí)承擔(dān)鏈路自協(xié)商、狀態(tài)檢測(cè)這些臟活。MIIMedia Independent Interface則是兩者間的語(yǔ)言規(guī)范常見的有RMII、RGMII、SGMII等不同接口決定了引腳數(shù)、時(shí)鐘方式和能跑的最高速率。驅(qū)動(dòng)開發(fā)時(shí)要記住一個(gè)關(guān)鍵點(diǎn)MAC和PHY之間不是簡(jiǎn)單的主從關(guān)系而是一條雙向協(xié)商通道。MAC側(cè)說(shuō)我支持千兆PHY側(cè)說(shuō)我可以千兆物理介質(zhì)上才能以千兆速率把鏈路拉起來(lái)。兩者任何一個(gè)撒謊結(jié)果就是表面上設(shè)備存在、驅(qū)動(dòng)加載正常實(shí)際卻link down。1.2 從PCI/設(shè)備樹到net_device驅(qū)動(dòng)掛載的順序理解驅(qū)動(dòng)加載順序才能看懂dmesg里那些日志。以X86嵌入式平臺(tái)為例Intel I219-V這類網(wǎng)卡走PCIe總線內(nèi)核先在PCI枚舉階段發(fā)現(xiàn)設(shè)備然后由對(duì)應(yīng)驅(qū)動(dòng)如e1000e的probe回調(diào)接管而在ARM/FPGA平臺(tái)上走的是設(shè)備樹描述MAC節(jié)點(diǎn)通過(guò)compatible屬性匹配到平臺(tái)驅(qū)動(dòng)PHY掛在MDIO總線上由PHY驅(qū)動(dòng)識(shí)別。無(wú)論哪種路徑最后都會(huì)走到同一個(gè)出口注冊(cè)net_device調(diào)用ndo_open此時(shí)MAC驅(qū)動(dòng)會(huì)做三件事——配置MAC控制器的時(shí)鐘與復(fù)位、啟動(dòng)DMA描述符環(huán)、然后觸發(fā)PHY的狀態(tài)機(jī)開始自協(xié)商。我習(xí)慣把這一步叫做三方握手PCI/設(shè)備樹只是把設(shè)備認(rèn)出來(lái)了真正讓網(wǎng)口能用的是open時(shí)MAC和PHY之間的交互。1.3 第一步硬件摸底把設(shè)備挖出來(lái)拿到板子先別急著改代碼先把硬件身份確認(rèn)了。X86平臺(tái)下最直接的是lspci -nn | grep -i ethernet lspci -vvv -s 00:1f.6第一行能告訴你設(shè)備編號(hào)第二行能看到LnkCap/LnkSta、中斷號(hào)、BAR空間以及EEPROM里固化的MAC地址。我遇到過(guò)不止一次批量板卡MAC地址全寫入同一個(gè)值的情況那就是工廠燒錄環(huán)節(jié)的問(wèn)題跟驅(qū)動(dòng)沒(méi)關(guān)系。如果是ARM平臺(tái)看設(shè)備樹里MAC節(jié)點(diǎn)的status狀態(tài)是不是okayPHY節(jié)點(diǎn)有沒(méi)有正確引用MDIO子節(jié)點(diǎn)。還有個(gè)小技巧解析設(shè)備樹時(shí)用dtc -I fs -O dts /proc/device-tree導(dǎo)出當(dāng)前實(shí)際生效的設(shè)備樹比翻源碼里的dtsi靠譜得多——因?yàn)閎ootloader可能覆蓋了部分屬性。這一節(jié)的核心思路概括成一句話遇到網(wǎng)口問(wèn)題先分清是哪一段在喊痛。PCI枚舉失敗是硬件識(shí)別問(wèn)題net_device注冊(cè)了但link up不上是MAC-PHY協(xié)商問(wèn)題鏈路速率正常卻丟包嚴(yán)重又是DMA和中斷配置的問(wèn)題。方向錯(cuò)了后面全是無(wú)用功。2. Intel I219-V 在嵌入式板卡上的適配不止是e1000e能用就行2.1 I219-V為什么出現(xiàn)在工業(yè)板卡Intel I219-V全稱Intel(R) Ethernet Connection (16) I219-V是一款集成在Intel芯片組里的千兆以太網(wǎng)控制器廣泛出現(xiàn)在各類x86工控板、嵌入式BOXPC和邊緣計(jì)算設(shè)備上。它沒(méi)有獨(dú)立PHY芯片而是通過(guò)板級(jí)線路直接把SerDes接到RJ45或內(nèi)部PHY驅(qū)動(dòng)是內(nèi)核里經(jīng)典的e1000e。選它做工業(yè)板卡的理由很樸素生態(tài)成熟、CPU占用低、驅(qū)動(dòng)常年穩(wěn)定。但穩(wěn)定不代表不需要適配。e1000e雖然主線上一直在維護(hù)具體到某個(gè)板卡廠商的定制設(shè)計(jì)仍然會(huì)出現(xiàn)EEPROM配置、LED極性、Wake-on-LAN等細(xì)節(jié)問(wèn)題需要針對(duì)板卡做定制。2.2 加載e1000e驅(qū)動(dòng)后第一步確認(rèn)什么驅(qū)動(dòng)加載成功后我一般依次看三樣?xùn)|西ethtool -i enp0s31f6 ethtool enp0s31f6 ethtool -k enp0s31f6ethtool -i確認(rèn)driver名稱、固件版本和總線位置ethtool查看速率、自協(xié)商狀態(tài)、wake-on設(shè)置ethtool -k查offload特性重點(diǎn)看tx-checksumming、tcp-segmentation-offload、vlan-offload。I219-V對(duì)TSOTCP Segmentation Offload和VLAN offload支持都很好但有時(shí)板級(jí)設(shè)計(jì)有缺陷時(shí)需要臨時(shí)關(guān)掉這些特性后面會(huì)詳細(xì)說(shuō)。還有一個(gè)容易被忽略的檢查項(xiàng)EEPROM里的MAC地址和PCI配置空間是否一致。通過(guò)ethtool -e enp0s31f6可以dump EEPROM內(nèi)容做備份。工業(yè)現(xiàn)場(chǎng)設(shè)備多運(yùn)維經(jīng)常要按MAC地址管理資產(chǎn)如果出廠燒錄環(huán)節(jié)出了岔子驅(qū)動(dòng)層面是無(wú)解的。2.3 VLAN配置的兩種路徑與offload陷阱給I219-V配VLAN大多數(shù)人第一反應(yīng)是用ip link命令ip link add link enp0s31f6 name enp0s31f6.100 type vlan id 100 ip link set enp0s31f6.100 up ip addr add 192.168.100.10/24 dev enp0s31f6.100這套命令本身沒(méi)問(wèn)題但嵌入式工程師還要問(wèn)一句VLAN tag的添加和剝離是在CPU里軟處理還是由網(wǎng)卡硬件完成如果e1000e啟用了VLAN offload默認(rèn)開啟那收包時(shí)硬件已經(jīng)剝掉了tag內(nèi)核看到的skb不帶VLAN頭而是帶著VLAN_CFI/VLAN_VID元數(shù)據(jù)走專用路徑。這種情況下如果上層應(yīng)用直接抓包看raw socket會(huì)發(fā)現(xiàn)看不到VLAN標(biāo)簽——這不是丟包而是硬件加速生效了。反過(guò)來(lái)如果遇到VLAN口收不到廣播報(bào)文、或者tcpdump看到重復(fù)的VLAN層多半是offload和軟件處理形成了矛盾。排查命令ethtool -k enp0s31f6 | grep vlan ip link show enp0s31f6.100實(shí)際項(xiàng)目里我會(huì)根據(jù)業(yè)務(wù)場(chǎng)景決定是否保留VLAN offload。單純跑ModbusTCP、EtherNet/IP這類普通業(yè)務(wù)流offload開不開影響不大但涉及工控報(bào)文深度解析、旁路抓包分析時(shí)建議先統(tǒng)一關(guān)掉再做測(cè)試避免排查時(shí)被硬件幫忙處理了這個(gè)隱藏因素干擾。2.4 性能調(diào)整隊(duì)列、中斷合并與功耗平衡I219-V雖然不像高端網(wǎng)卡那樣有幾十個(gè)隊(duì)列但它同樣支持多個(gè)DMA隊(duì)列和RSSReceive Side Scaling。在嵌入式Linux里可以通過(guò)ethtool -L調(diào)整隊(duì)列數(shù)量ethtool -L enp0s31f6 combined 1 ethtool -L enp0s31f6 combined 4隊(duì)列少好管理但多核平臺(tái)上高吞吐場(chǎng)景也會(huì)受限于單核中斷隊(duì)列多又可能讓緩存命中率下降。工業(yè)場(chǎng)景我通常先用combined 1保證邏輯簡(jiǎn)單遇到吞吐瓶頸再逐步加大。中斷合并是另一個(gè)關(guān)鍵點(diǎn)。e1000e默認(rèn)為了吞吐會(huì)盡量合并中斷但這會(huì)帶來(lái)不確定的延遲抖動(dòng)。等會(huì)兒第5節(jié)講EtherNet/IP時(shí)會(huì)專門展開這里先記住一條命令ethtool -C enp0s31f6 rx-usecs 0 tx-usecs 0把合并關(guān)到最低延遲上來(lái)了但確定性變好。功耗方面ethtool --set-phy-tunable enp0s31f6 downshift 0這類參數(shù)在I219-V上不一定都支持更多是控制EEE節(jié)能以太網(wǎng)。工業(yè)現(xiàn)場(chǎng)我建議關(guān)掉EEE因?yàn)樗鼤?huì)在鏈路空閑時(shí)進(jìn)入低功耗模式有些交換機(jī)和遠(yuǎn)端設(shè)備配合不好會(huì)導(dǎo)致鏈路偶發(fā)斷連。3. SGMII、PCS/PMA與1G/2.5G速率MAC和PHY之間沒(méi)說(shuō)的線速秘密3.1 用快遞分揀理解SGMII的每秒1.25GRGMII用4對(duì)數(shù)據(jù)線并行傳千兆SGMII則把線減到1對(duì)差分線跑1.25Gbps的串行碼流。很多工程師第一次聽到千兆用1.25G串行線都覺得矛盾數(shù)據(jù)明明只有1G怎么線速是1.25G其實(shí)多出來(lái)的25%是8b/10b編碼開銷——每8bit數(shù)據(jù)編碼成10bit線上符號(hào)目的是保證直流平衡和時(shí)間同步。這就好比快遞分揀時(shí)為了確保包裹不丟不錯(cuò)每個(gè)包裹都額外貼了一張帶校驗(yàn)碼的面單面單本身也占體積。所以SGMII的本質(zhì)是把MAC數(shù)據(jù)流先做8b/10b編碼串行化后送出。這個(gè)編碼過(guò)程可以由MAC內(nèi)置完成也可以由外置的PCS/PMA芯片完成。在FPGA的以太網(wǎng)IP核里這就對(duì)應(yīng)最常見的配置選項(xiàng)1G/2.5G Ethernet PCS/PMA or SGMII。3.2 PCS/PMA在FPGA/SoC里的角色FPGA做以太網(wǎng)端口擴(kuò)展時(shí)Xilinx現(xiàn)在叫AMD的1G/2.5G Ethernet PCS/PMA or SGMIIIP核是繞不開的。它承擔(dān)了PCS物理編碼子層和PMA物理介質(zhì)接入子層的功能內(nèi)部可以做SGMII接口、也可以直接做1000BASE-X/2500BASE-X光口模式。PCS負(fù)責(zé)編碼、自協(xié)商AN、鏈路狀態(tài)跟蹤PMA負(fù)責(zé)高速串行收發(fā)也就是說(shuō)PMA直接對(duì)接板上的SerDes引腳。在Zynq平臺(tái)中常見的接法是PS端GEM通過(guò)SGMII接到片外PHY如Marvell 88E1512、Realtek RTL8211或者PL端以太網(wǎng)IP核通過(guò)SGMII/1000BASE-X接到PHY/光模塊。設(shè)備樹里對(duì)應(yīng)的描述是gem0 { phy-mode sgmii; phy-handle phy0; phy0: phy0 { reg 0; device_type ethernet-phy; }; };phy-mode驅(qū)動(dòng)了驅(qū)動(dòng)側(cè)對(duì)MAC接口模式的配置必須和實(shí)際硬件設(shè)計(jì)嚴(yán)格一致。這個(gè)屬性配錯(cuò)了MAC側(cè)的數(shù)據(jù)收發(fā)時(shí)序就會(huì)完全錯(cuò)位。3.3 速率協(xié)商失敗的經(jīng)典現(xiàn)場(chǎng)SGMII場(chǎng)景最典型的故障是PHY協(xié)商成100M甚至10M但MAC側(cè)還鎖在1000M。SGMII的自協(xié)商機(jī)制里MAC和PHY之間會(huì)傳遞速率信息可如果中間的PCS/PMA配置成了固定速率模式或者IP核把AN功能關(guān)閉了兩邊就不在同一個(gè)頻道上。我曾經(jīng)處理過(guò)一個(gè)板卡PHY用的是RTL8211MAC側(cè)是Zynq GEMphy-mode寫的是rgmii-id但硬件實(shí)際走的是SGMII結(jié)果Link Up后收包全是FCS錯(cuò)誤。內(nèi)核日志里會(huì)反復(fù)刷macb f8008000.ethernet eth0: link up (1000Mbps/Full duplex) macb f8008000.ethernet eth0: link up (1000Mbps/Full duplex)看著是up了其實(shí)MAC在不停重傳。最后定位是設(shè)備樹接口模式和實(shí)際硬件不匹配。所以排查這類問(wèn)題第一步永遠(yuǎn)是檢查接口模式屬性與實(shí)際電路的對(duì)照關(guān)系比看寄存器快得多。3.4 2.5G速率模式別想當(dāng)然2.5G Ethernet和SGMII之間很容易混淆。標(biāo)準(zhǔn)SGMII按協(xié)議只能跑10/100/1000M2.5G速率下接口形態(tài)雖然和SGMII很像但跑的是2500BASE-X沒(méi)有自協(xié)商機(jī)制鏈路兩端必須強(qiáng)制設(shè)定相同速率。很多工程師在FPGA里配置了2.5G PCS/PMA然后拿標(biāo)準(zhǔn)SGMII去對(duì)端對(duì)接結(jié)果駐留相位正確但雙方速率認(rèn)知不一致鏈路始終無(wú)法起來(lái)。實(shí)際調(diào)試時(shí)要確認(rèn)的清單很短但都很關(guān)鍵MAC側(cè)是否支持2.5G速率上報(bào)、PCS/PMA IP核是否選對(duì)了2.5G模式、對(duì)端交換端口是否強(qiáng)制2500M、線纜和連接器是否支持2.5G SerDes速率。漏掉任何一項(xiàng)就可能出現(xiàn)link指示燈亮但數(shù)據(jù)不通的假象。2.5G應(yīng)用我還有個(gè)建議先用iperf3做雙向打流確認(rèn)實(shí)測(cè)速率不要只看ethtool顯示的協(xié)商速率——速率上報(bào)機(jī)制在非標(biāo)模式下經(jīng)常是假的。4. 從dmesg和netlink日志挖出link up但ping不通的根因4.1 網(wǎng)口驅(qū)動(dòng)初始化的時(shí)間線一個(gè)網(wǎng)口從驅(qū)動(dòng)加載到能正常收發(fā)內(nèi)核日志里其實(shí)有條清晰的時(shí)間線。我處理這類問(wèn)題時(shí)喜歡先把dmesg里所有相關(guān)日志粘出來(lái)標(biāo)上序號(hào)[ 12.345] e1000e 0000:00:1f.6 eth0: (PCI Express:2.5GT/s:Width x1) [ 12.351] e1000e 0000:00:1f.6 eth0: MAC: 3, PHY: 7, PBA No: E5020-008 [ 12.357] e1000e 0000:00:1f.6 eth0: Intel(R) PRO/1000 Network Connection [ 12.363] e1000e 0000:00:1f.6 enp0s31f6: renamed from eth0 [ 12.789] IPv6: ADDRCONF(NETDEV_UP): enp0s31f6: link is not readylink is not ready出現(xiàn)在這里很正常因?yàn)榇藭r(shí)IP層配置已經(jīng)完成但驅(qū)動(dòng)還沒(méi)觸發(fā)PHY自協(xié)商。真正的link up日志要等ifconfig up之后才出現(xiàn)。很多誤報(bào)驅(qū)動(dòng)掛了的板子其實(shí)只是日志看少了后面半段。4.2 PHY狀態(tài)機(jī)是怎么跑的內(nèi)核PHY子系統(tǒng)有一套標(biāo)準(zhǔn)狀態(tài)機(jī)背后對(duì)應(yīng)了一個(gè)workqueue周期調(diào)度。狀態(tài)機(jī)從PHY_DOWN開始o(jì)pen后進(jìn)入PHY_UP然后向PHY_AN發(fā)起自協(xié)商協(xié)商完成進(jìn)入PHY_RUNNING如果鏈路斷開會(huì)退回PHY_NOLINK并周期性重試。內(nèi)核里一旦PHY狀態(tài)變化會(huì)通過(guò)netlink發(fā)送RTM_NEWLINK最終反映到用戶態(tài)就是carrier的變化。調(diào)試的時(shí)候關(guān)注兩個(gè)位置/sys/class/net/enp0s31f6/carrier的值以及/sys/class/net/enp0s31f6/operstate。前者是物理鏈路是否通暢后者是協(xié)議棧對(duì)鏈路可用性的判斷。如果carrier1但operstatedown基本可以斷定是上層配置問(wèn)題比如沒(méi)配IP、沒(méi)up如果carrier來(lái)回跳就是物理鏈路在閃斷。4.3 快速定位的四類現(xiàn)場(chǎng)根據(jù)經(jīng)驗(yàn)link up但ping不通的問(wèn)題可以歸成四類現(xiàn)象常見原因快速定位手段link反復(fù)up/downPHY復(fù)位設(shè)計(jì)不良、電源噪聲、交換端強(qiáng)制模式dmesg頻率統(tǒng)計(jì)換端口驗(yàn)證link持續(xù)up但收不到包VLAN tag錯(cuò)配、offload不匹配、MAC地址過(guò)濾tcpdump抓包看VLAN/源MAC收發(fā)都不通接口模式phy-mode與硬件不符檢查設(shè)備樹與原理圖只能小包通大包不通MTU不一致、TSO/GSO問(wèn)題分別ping -s 1472和9000測(cè)試這里最想提醒的是MTU問(wèn)題。嵌入式設(shè)備默認(rèn)MTU是1500但如果對(duì)端交換機(jī)配置了巨型幀或VLAN透?jìng)鲿r(shí)MTU加了4字節(jié)就會(huì)出現(xiàn)小包通、大包卡的經(jīng)典故障。排查命令也很簡(jiǎn)單ping -M do -s 1472和ping -M do -s 8000分別測(cè)一下再對(duì)比兩端MTU設(shè)置即可。4.4 rgmii-id與外部PHY的相位坑RGMII接口本身存在時(shí)鐘和數(shù)據(jù)線的相位對(duì)齊問(wèn)題所以標(biāo)準(zhǔn)里定義了不同的延遲模式rgmii-id表示TX和RX都加內(nèi)部延遲rgmii-txid只加TX延遲rgmii-rxid只加RX延遲。很多人把這個(gè)屬性當(dāng)成擺設(shè)實(shí)際在PHY芯片選型和PCB布線不同的情況下差的正是這一點(diǎn)延遲直接導(dǎo)致采到的數(shù)據(jù)全是錯(cuò)位比特。處理建議是拿到一塊新板子如果網(wǎng)口link up但收包不正常先把設(shè)備樹里phy-mode從rgmii-id換成rgmii-rxid或rgmii-txid試試。有次我在一塊定制的AM335x板卡上排查默認(rèn)rgmii-id下FCS錯(cuò)誤率高達(dá)30%改成rgmii-txid后錯(cuò)誤率直接歸零。這種問(wèn)題光看寄存器很難看出名堂偏偏改一個(gè)設(shè)備樹字符串就能解決。5. 為EtherNet/IP這類工業(yè)協(xié)議服務(wù)的驅(qū)動(dòng)特調(diào)5.1 工業(yè)協(xié)議對(duì)網(wǎng)卡驅(qū)動(dòng)的三個(gè)隱性要求EtherNet/IP是基于標(biāo)準(zhǔn)以太網(wǎng)的工業(yè)協(xié)議CIP報(bào)文跑在TCP/UDP之上。很多人認(rèn)為跑標(biāo)準(zhǔn)TCP/IP驅(qū)動(dòng)不用特別改但真正部署產(chǎn)線時(shí)你會(huì)發(fā)現(xiàn)工業(yè)現(xiàn)場(chǎng)對(duì)底層驅(qū)動(dòng)有超出能通之外的要求一是確定性延遲報(bào)文到達(dá)和發(fā)出的時(shí)間抖動(dòng)要小二是穩(wěn)定優(yōu)先級(jí)排除中斷合并和驅(qū)動(dòng)bug造成的偶發(fā)超時(shí)三是異常報(bào)文處理能力比如廣播風(fēng)暴下不能把CPU打滿。所以驅(qū)動(dòng)層面的調(diào)優(yōu)思路和通用服務(wù)器不一樣。服務(wù)器追求高吞吐可以大開中斷合并工業(yè)實(shí)時(shí)場(chǎng)景則要壓低延遲抖動(dòng)必要時(shí)犧牲一點(diǎn)吞吐。5.2 中斷合并關(guān)閉與NAPI先看中斷合并。e1000e驅(qū)動(dòng)默認(rèn)的rx-usecs不是0意味著收包后不會(huì)立刻觸發(fā)中斷而是攢一段時(shí)間或攢夠數(shù)量再上報(bào)。對(duì)EtherNet/IP這種要求循環(huán)周期穩(wěn)定的應(yīng)用這個(gè)攢的動(dòng)作就是不確定性的根源。建議直接關(guān)ethtool -C enp0s31f6 rx-usecs 0 tx-usecs 0 rx-frames 1 tx-frames 1NAPI那邊不用特別關(guān)。內(nèi)核里NAPI的輪詢機(jī)制本來(lái)就是處理高吞吐的有效手段而且中斷NAPI的組合在工業(yè)場(chǎng)景下表現(xiàn)很好。重點(diǎn)是別在驅(qū)動(dòng)里隨便加modprobe e1000e InterruptThrottleRate0這類全局參數(shù)I219-V的驅(qū)動(dòng)參數(shù)雖然支持但全局禁用對(duì)性能和CPU占用影響很大不如針對(duì)單個(gè)接口用ethtool做精準(zhǔn)控制。5.3 隊(duì)列、中斷親和性與CPU隔離當(dāng)設(shè)備有多隊(duì)列可以把網(wǎng)卡中斷綁定到指定CPU核心避免中斷在各個(gè)核之間漂移。常見做法是查/proc/irq/下對(duì)應(yīng)中斷號(hào)寫到/proc/irq/N/smp_affinity。但注意嵌入式平臺(tái)的CPU核數(shù)少盲目綁定可能適得其反建議先壓測(cè)確認(rèn)瓶頸確實(shí)在中斷漂移上再做綁定。如果是EtherNet/IP協(xié)議棧比如EtherNet/IP Scanner/Adapter部署在Linux用戶態(tài)還建議把網(wǎng)卡的協(xié)議處理CPU與實(shí)時(shí)控制CPU分開。Linux的isolcpus內(nèi)核參數(shù)可以隔離出專屬核配合sched_setaffinity把協(xié)議棧線程固定到非隔離核驅(qū)動(dòng)中斷固定到另一個(gè)核這樣能有效降低協(xié)議棧線程被搶占的概率。5.4 驅(qū)動(dòng)版本與PHY固件的別輕易動(dòng)最后這條是經(jīng)驗(yàn)教訓(xùn)。工業(yè)設(shè)備網(wǎng)卡驅(qū)動(dòng)一旦穩(wěn)定不要因?yàn)閮?nèi)核升級(jí)了順手更新一下就隨意換驅(qū)動(dòng)版本。e1000e這類驅(qū)動(dòng)在不同內(nèi)核版本上的行為差異不少尤其涉及PCIe電源管理、EEE、VLAN offload的部分。曾經(jīng)有客戶把內(nèi)核從4.19升到5.10I219-V網(wǎng)卡在低流量時(shí)出現(xiàn)偶發(fā)斷流最后定位是新的驅(qū)動(dòng)默認(rèn)開啟了EEE而板載PHY對(duì)端設(shè)備不支持正確的喚醒序列。解決方案不是打補(bǔ)丁而是關(guān)掉EEE參數(shù)。固件和EEPROM同理。ethtool -S里能看到tx_timeout、rx_errors等統(tǒng)計(jì)如果這些計(jì)數(shù)長(zhǎng)期為0就不要去碰固件升級(jí)。網(wǎng)絡(luò)設(shè)備在產(chǎn)線上跑得好好的任何不必要的變更都是在引入風(fēng)險(xiǎn)。給現(xiàn)場(chǎng)維護(hù)團(tuán)隊(duì)的建議永遠(yuǎn)是先備份當(dāng)前驅(qū)動(dòng)版本、固件版本和配置命令再考慮任何升級(jí)操作。這一期從驅(qū)動(dòng)鏈路的基礎(chǔ)認(rèn)知聊到具體芯片適配、接口速率、狀態(tài)機(jī)排錯(cuò)再到工業(yè)協(xié)議場(chǎng)景下的驅(qū)動(dòng)特調(diào)算是把嵌入式以太網(wǎng)驅(qū)動(dòng)開發(fā)中容易出問(wèn)題的幾塊硬骨頭都啃了一遍。如果讓我總結(jié)一條最實(shí)用的經(jīng)驗(yàn)?zāi)蔷褪蔷W(wǎng)口故障別急著改代碼先沿著PCI/設(shè)備樹識(shí)別 → MAC-PHY協(xié)商 → 鏈路狀態(tài) → offload配置 → 協(xié)議棧行為這條鏈路逐層驗(yàn)證絕大多數(shù)問(wèn)題都能在半小時(shí)內(nèi)定位到具體環(huán)節(jié)。至于SGMII的速率陷阱、RGMII的相位細(xì)節(jié)、VLAN offload的隱性問(wèn)題這些都是需要拿板子實(shí)測(cè)才能沉淀下來(lái)的經(jīng)驗(yàn)光看芯片手冊(cè)遠(yuǎn)遠(yuǎn)不夠。