• 正文
    • 1. 了解接收數(shù)據(jù)包的流程
    • 2. ifconfig 解釋
    • 3. 網卡工作原理
    • 4. 丟包排查思路
  • 相關推薦
申請入駐 產業(yè)圖譜

ethtool 原理介紹和解決網卡丟包排查思路

2023/03/20
2702
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

之前記錄過處理因為 LVS 網卡流量負載過高導致軟中斷發(fā)生丟包的問題,RPS 和 RFS 網卡多隊列性能調優(yōu)實踐[1],對一般人來說壓力不大的情況下其實碰見的概率并不高。這次想分享的話題是比較常見服務器網卡丟包現(xiàn)象排查思路,如果你是想了解點對點的丟包解決思路涉及面可能就比較廣,不妨先參考之前的文章如何使用 MTR 診斷網絡問題[2],對于 Linux 常用的網卡丟包分析工具自然是 ethtool。

ethtool 用于查看和修改網絡設備(尤其是有線以太網設備)的驅動參數(shù)和硬件設置。你可以根據(jù)需要更改以太網卡的參數(shù),包括自動協(xié)商、速度、雙工和局域網喚醒等參數(shù)。通過對以太網卡的配置,你的計算機可以通過網絡有效地進行通信。該工具提供了許多關于接駁到你的 Linux 系統(tǒng)的以太網設備的信息。

1. 了解接收數(shù)據(jù)包的流程

接收數(shù)據(jù)包是一個復雜的過程,涉及很多底層的技術細節(jié),但大致需要以下幾個步驟:

    網卡收到數(shù)據(jù)包。將數(shù)據(jù)包從網卡硬件緩存轉移到服務器內存中。通知內核處理。經過 TCP/IP 協(xié)議逐層處理。應用程序通過 read() 從 socket buffer 讀取數(shù)據(jù)。

將網卡收到的數(shù)據(jù)包轉移到主機內存(NIC 與驅動交互)

NIC 在接收到數(shù)據(jù)包之后,首先需要將數(shù)據(jù)同步到內核中,這中間的橋梁是 rx ring buffer。它是由 NIC 和驅動程序共享的一片區(qū)域,事實上,rx ring buffer 存儲的并不是實際的 packet 數(shù)據(jù),而是一個描述符,這個描述符指向了它真正的存儲地址,具體流程如下:

    驅動在內存中分配一片緩沖區(qū)用來接收數(shù)據(jù)包,叫做 sk_buffer;將上述緩沖區(qū)的地址和大小(即接收描述符),加入到 rx ring buffer。描述符中的緩沖區(qū)地址是 DMA 使用的物理地址;驅動通知網卡有一個新的描述符;網卡從 rx ring buffer 中取出描述符,從而獲知緩沖區(qū)的地址和大??;網卡收到新的數(shù)據(jù)包;網卡將新數(shù)據(jù)包通過 DMA 直接寫到 sk_buffer 中。

當驅動處理速度跟不上網卡收包速度時,驅動來不及分配緩沖區(qū),NIC 接收到的數(shù)據(jù)包無法及時寫到 sk_buffer,就會產生堆積,當 NIC 內部緩沖區(qū)寫滿后,就會丟棄部分數(shù)據(jù),引起丟包。這部分丟包為 rx_fifo_errors,在 /proc/net/dev 中體現(xiàn)為 fifo 字段增長,在 ifconfig 中體現(xiàn)為 overruns 指標增長。

通知系統(tǒng)內核處理(驅動與 Linux 內核交互)

這個時候,數(shù)據(jù)包已經被轉移到了 sk_buffer 中。前文提到,這是驅動程序在內存中分配的一片緩沖區(qū),并且是通過 DMA 寫入的,這種方式不依賴 CPU 直接將數(shù)據(jù)寫到了內存中,意味著對內核來說,其實并不知道已經有新數(shù)據(jù)到了內存中。那么如何讓內核知道有新數(shù)據(jù)進來了呢?答案就是中斷,通過中斷告訴內核有新數(shù)據(jù)進來了,并需要進行后續(xù)處理。

提到中斷,就涉及到硬中斷和軟中斷,首先需要簡單了解一下它們的區(qū)別:

    硬中斷:由硬件自己生成,具有隨機性,硬中斷被 CPU 接收后,觸發(fā)執(zhí)行中斷處理程序。中斷處理程序只會處理關鍵性的、短時間內可以處理完的工作,剩余耗時較長工作,會放到中斷之后,由軟中斷來完成。硬中斷也被稱為上半部分。軟中斷:由硬中斷對應的中斷處理程序生成,往往是預先在代碼里實現(xiàn)好的,不具有隨機性。(除此之外,也有應用程序觸發(fā)的軟中斷,與本文討論的網卡收包無關。)也被稱為下半部分。

當 NIC 把數(shù)據(jù)包通過 DMA 復制到內核緩沖區(qū) sk_buffer 后,NIC 立即發(fā)起一個硬件中斷。CPU 接收后,首先進入上半部分,網卡中斷對應的中斷處理程序是網卡驅動程序的一部分,之后由它發(fā)起軟中斷,進入下半部分,開始消費 sk_buffer 中的數(shù)據(jù),交給內核協(xié)議棧處理。

通過中斷,能夠快速及時地響應網卡數(shù)據(jù)請求,但如果數(shù)據(jù)量大,那么會產生大量中斷請求,CPU 大部分時間都忙于處理中斷,效率很低。為了解決這個問題,現(xiàn)在的內核及驅動都采用一種叫 NAPI(new API)的方式進行數(shù)據(jù)處理,其原理可以簡單理解為 中斷 + 輪詢,在數(shù)據(jù)量大時,一次中斷后通過輪詢接收一定數(shù)量包再返回,避免產生多次中斷。

2. ifconfig 解釋

[root@localhost?~]
eth0:?flags=4163<UP,BROADCAST,RUNNING,MULTICAST>?mtu?1500
inet?192.168.1.135?netmask?255.255.255.0?broadcast?192.168.1.255
inet6?fe80::20c:29ff:fe9b:52d3?prefixlen?64?scopeid?0x20<link>
ether?00:0c:29:9b:52:d3?txqueuelen?1000?(Ethernet)
RX?packets?833?bytes?61846?(60.3?KiB)
RX?errors?0?dropped?0?overruns?0?frame?0
TX?packets?122?bytes?9028?(8.8?KiB)
TX?errors?0?dropped?0?overruns?0?carrier?0?collisions?0
    RX errors

表示總的收包的錯誤數(shù)量,這包括 too-long-frames 錯誤,Ring Buffer 溢出錯誤,crc 校驗錯誤,幀同步錯誤,fifo overruns 以及 missed pkg 等等。

    RX dropped

表示數(shù)據(jù)包已經進入了 Ring Buffer,但是由于內存不夠等系統(tǒng)原因,導致在拷貝到內存的過程中被丟棄。

    RX overruns

表示了 fifo 的 overruns,這是由于 Ring Buffer(aka Driver Queue) 傳輸?shù)?IO 大于 kernel 能夠處理的 IO 導致的,而 Ring Buffer 則是指在發(fā)起 IRQ 請求之前的那塊 buffer。很明顯,overruns 的增大意味著數(shù)據(jù)包沒到 Ring Buffer 就被網卡物理層給丟棄了,而 CPU 無法即使的處理中斷是造成 Ring Buffer 滿的原因之一,上面那臺有問題的機器就是因為 interruprs 分布的不均勻 (都壓在 core0),沒有做 affinity 而造成的丟包。

    RX frame

表示 misaligned 的 frames。

3. 網卡工作原理

網卡發(fā)包

網卡驅動程序將 IP 包添加 14 字節(jié)的 MAC 頭,構成 frame(暫無 CRC)。Frame(暫無 CRC)中含有發(fā)送端和接收端的 MAC 地址,由于是驅動程序創(chuàng)建 MAC 頭,所以可以隨便輸入地址,也可以進行主機偽裝。

驅動程序將 frame(暫無 CRC)拷貝到網卡芯片內部的緩沖區(qū),由網卡處理。

網卡芯片將未完全完成的 frame(缺 CRC)再次封裝為可以發(fā)送的 packet,也就是添加頭部同步信息和 CRC 校驗,然后丟到網線上,就完成一個 IP 報的發(fā)送了,所有接到網線上的網卡都可以看到該 packet。

網卡收包

網線上的 packet 首先被網卡獲取,網卡會檢查 packet 的 CRC 校驗,保證完整性,然后將 packet 頭去掉,得到 frame。網卡會檢查 MAC 包內的目的 MAC 地址,如果和本網卡的 MAC 地址不一樣則丟棄 (混雜模式除外)。

網卡將 frame 拷貝到網卡內部的 FIFO 緩沖區(qū),觸發(fā)硬件中斷。(如有 ring buffer 的網卡,好像 frame 可以先存在 ring buffer 里再觸發(fā)軟件中斷(下篇文章將詳細解釋 Linux 中 frame 的走向),ring buffer 是網卡和驅動程序共享,是設備里的內存,但是對操作系統(tǒng)是可見的,因為看到 linux 內核源碼里網卡驅動程序是使用 kcalloc 來分配的空間,所以 ring buffer 一般都有上限,另外這個 ring buffer size,表示的應該是能存儲的 frame 的個數(shù),而不是字節(jié)大小。另外有些系統(tǒng)的 ethtool 命令 并不能改變 ring parameters 來設置 ring buffer 的大小,暫時不知道為什么,可能是驅動不支持。)

網卡驅動程序通過硬中斷處理函數(shù),構建 sk_buff,把 frame 從網卡 FIFO 拷貝到內存 skb 中,接下來交給內核處理。(支持 napi 的網卡應該是直接放在 ring buffer,不觸發(fā)硬中斷,直接使用軟中斷,拷貝 ring buffer 里的數(shù)據(jù),直接輸送給上層處理,每個網卡在一次軟中斷處理過程能處理 weight 個 frame)

過程中,網卡芯片對 frame 進行了 MAC 過濾,以減小系統(tǒng)負荷。(除了混雜模式)

網卡中斷處理函數(shù)

產生中斷的每個設備都有一個相應的中斷處理程序,是設備驅動程序的一部分。每個網卡都有一個中斷處理程序,用于通知網卡該中斷已經被接收了,以及把網卡緩沖區(qū)的數(shù)據(jù)包拷貝到內存中。

當網卡接收來自網絡的數(shù)據(jù)包時,需要通知內核數(shù)據(jù)包到了。網卡立即發(fā)出中斷。內核通過執(zhí)行網卡已注冊的中斷處理函數(shù)來做出應答。中斷處理程序開始執(zhí)行,通知硬件,拷貝最新的網絡數(shù)據(jù)包到內存,然后讀取網卡更多的數(shù)據(jù)包。

這些都是重要、緊迫而又與硬件相關的工作。內核通常需要快速的拷貝網絡數(shù)據(jù)包到系統(tǒng)內存,因為網卡上接收網絡數(shù)據(jù)包的緩存大小固定,而且相比系統(tǒng)內存也要小得多。所以上述拷貝動作一旦被延遲,必然造成網卡 FIFO 緩存溢出 - 進入的數(shù)據(jù)包占滿了網卡的緩存,后續(xù)的包只能被丟棄,這也應該就是 ifconfig 里的 overrun 的來源。

當網絡數(shù)據(jù)包被拷貝到系統(tǒng)內存后,中斷的任務算是完成了,這時它把控制權交還給被系統(tǒng)中斷前運行的程序。

緩沖區(qū)訪問

網卡的內核緩沖區(qū),是在 PC 內存中,由內核控制,而網卡會有 FIFO 緩沖區(qū),或者 ring buffer,這應該將兩者區(qū)分開。FIFO 比較小,里面有數(shù)據(jù)便會盡量將數(shù)據(jù)存在內核緩沖中。

網卡中的緩沖區(qū)既不屬于內核空間,也不屬于用戶空間。它屬于硬件緩沖,允許網卡與操作系統(tǒng)之間有個緩沖;

內核緩沖區(qū)在內核空間,在內存中,用于內核程序,做為讀自或寫往硬件的數(shù)據(jù)緩沖區(qū);

用戶緩沖區(qū)在用戶空間,在內存中,用于用戶程序,做為讀自或寫往硬件的數(shù)據(jù)緩沖區(qū);

另外,為了加快數(shù)據(jù)的交互,可以將內核緩沖區(qū)映射到用戶空間,這樣,內核程序和用戶程序就可以同時訪問這一區(qū)間了。

對于有 ring buffer 的網卡,ring buffer 是由驅動與網卡共享的,所以內核可以直接訪問 ring buffer,一般拷貝 frames 的副本到自己的內核空間進行處理(deliver 到上層協(xié)議,之后的一個個 skb 就是按 skb 的指針傳遞方式傳遞,直到用戶獲得數(shù)據(jù),所以,對于 ring buffer 網卡,大量拷貝發(fā)生在 frame 從 ring buffer 傳遞到內核控制的計算機內存里)。

4. 丟包排查思路

網卡工作在數(shù)據(jù)鏈路層,數(shù)據(jù)量鏈路層,會做一些校驗,封裝成幀。我們可以查看校驗是否出錯,確定傳輸是否存在問題。然后從軟件層面,是否因為緩沖區(qū)太小丟包。

先查看硬件情況

一臺機器經常收到丟包的報警,先看看最底層的有沒有問題:

    查看工作模式是否正常
[root@localhost?~]#?ethtool?eth0?|?egrep?'Speed|Duplex'
Speed:?1000Mb/s
Duplex:?Full
    查看檢驗是否正常
[root@localhost?~]#?ethtool?-S?eth0?|?grep?crc
rx_crc_errors:?0

Speed,Duplex,CRC 之類的都沒問題,基本可以排除物理層面的干擾。

overruns 和 buffer size

for?i?in?`seq?1?100`;?do?ifconfig?eth2?|?grep?RX?|?grep?overruns;?sleep?1;?done

RX?packets:346547657?errors:0?dropped:0?overruns:35345?frame:0

-g???–show-ringQueries?the?specified?ethernet?device?for?rx/tx?ring?parameter?information.
-G???–set-ringChanges?the?rx/tx?ring?parameters?of?the?specified?ethernet?device.

ethtool?-g?eth0

[root@localhost?~]
Ring?parameters?for?eth0:
Pre-set?maximums:
RX:?4096
RX?Mini:?0
RX?Jumbo:?0
TX:?4096
Current?hardware?settings:
RX:?256
RX?Mini:?0
RX?Jumbo:?0
TX:?256

ethtool?-G?eth0?rx?2048
ethtool?-G?eth0?tx?2048

[root@localhost?~]
[root@localhost?~]
[root@localhost?~]
Ring?parameters?for?eth0:
Pre-set?maximums:
RX:?4096
RX?Mini:?0
RX?Jumbo:?0
TX:?4096
Current?hardware?settings:
RX:?2048
RX?Mini:?0
RX?Jumbo:?0
TX:?2048

Red Hat 官方解決思路

Issue

Why rx_crc_errors incrementing in the receive counter of ethtool -S output?

$?ethtool?-S?<Interface_name>?|?grep?-i?error
?????rx_error_bytes:?0
?????tx_error_bytes:?0
?????tx_mac_errors:?0
?????tx_carrier_errors:?0
?????rx_crc_errors:?9244
?????rx_align_errors:?0

Resolution

    Change the cable.Check switch configuration.Change the network interface card.

Root Cause

    Most of the time incrementing the value of rx_crc_errors means the problem is in Layer-1 of the networking model.When a packet is received at the interface, it goes through a data integrity check which is called cyclic redundancy check. If the packet fails in that check, it is marked as rx_crc_errors.The switch was forcing the NIC to operate in half-duplex mode. Fixing the switch to tell the NIC to operate in full-duplex mode have resolved the issue.

Diagnostic Steps

Check ethtool -S output and find where are the drops and errors.

$?ethtool?-S?<Interface_name>?|?grep?-i?error
?????rx_error_bytes:?0
?????tx_error_bytes:?0
?????tx_mac_errors:?0
?????tx_carrier_errors:?0
?????rx_crc_errors:?9244??>>>>>>
?????rx_align_errors:?0

Check the numbers corresponding to rx_crc_errors.

ethtool?p1p1

Settings?for?p1p1:
?Supported?ports:?[?FIBRE?]
?Supported?link?modes:???10000baseT/Full
?Supported?pause?frame?use:?Symmetric
?Supports?auto-negotiation:?No
?Supported?FEC?modes:?Not?reported
?Advertised?link?modes:??10000baseT/Full
?Advertised?pause?frame?use:?Symmetric
?Advertised?auto-negotiation:?No
?Advertised?FEC?modes:?Not?reported
?Speed:?10000Mb/s
?Duplex:?Full
?Port:?FIBRE
?PHYAD:?0
?Transceiver:?internal
?Auto-negotiation:?off
?Supports?Wake-on:?d
?Wake-on:?d
?Current?message?level:?0x00000007?(7)
??????????drv?probe?link
?Link?detected:?yes

顯示了 p1p1 的接口類型,連接模式,速率等等信息,以及當前是否連接了網線(如果是網線 Supported ports 就是 TP,如果是光纖則顯示 Fiber),這里例舉下 3 個重要關鍵詞:

Supported ports: [FIBRE]

Speed: 10000Mb/s

Link detected: yes

ethtool?-S?p1p1?|?grep?-i?error
?????rx_errors:?0
?????tx_errors:?0
?????rx_over_errors:?0
?????rx_crc_errors:?0
?????rx_frame_errors:?0
?????rx_fifo_errors:?0
?????rx_missed_errors:?0
?????tx_aborted_errors:?0
?????tx_carrier_errors:?0
?????tx_fifo_errors:?0
?????tx_heartbeat_errors:?0
?????rx_length_errors:?0
?????rx_long_length_errors:?0
?????rx_short_length_errors:?0
?????rx_csum_offload_errors:?0

ethtool?-p?<Interface_name>
ethtool?-p?eth0

ethtool?-i?p1p1

driver:?ixgbe
version:?5.1.0-k-rh7.6
firmware-version:?0x80000960,?18.3.6
expansion-rom-version:
bus-info:?0000:04:00.0
supports-statistics:?yes
supports-test:?yes
supports-eeprom-access:?yes
supports-register-dump:?yes
supports-priv-flags:?yes

ethtool?-s?eth0?speed?100

參考文章

ethtool[3]

Counters Troubleshooting for Linux Driver[4]

Why do I see rx_crc_errors in ethtool output?[5]

ping 請求錯誤分析[6]

ifconfig 命令詳解[7]

ethtool 命令詳解[8]

ethtool 解決網卡丟包嚴重和網卡原理[9]

腳注:

[1]RPS 和 RFS 網卡多隊列性能調優(yōu)實踐: https://wsgzao.github.io/post/rps/

[2]如何使用 MTR 診斷網絡問題: https://wsgzao.github.io/post/mtr/

[3]ethtool: https://mirrors.edge.kernel.org/pub/software/network/ethtool/

[4]Counters Troubleshooting for Linux Driver: https://community.mellanox.com/s/article/counters-troubleshooting-for-linux-driver

[5]Why do I see rx_crc_errors in ethtool output?: https://access.redhat.com/solutions/154543

[6]ping 請求錯誤分析: https://blog.csdn.net/u011857683/article/details/83663316

[7]ifconfig 命令詳解: https://blog.csdn.net/u011857683/article/details/83758503

[8]ethtool 命令詳解: https://blog.csdn.net/u011857683/article/details/83758689

[9]ethtool 解決網卡丟包嚴重和網卡原理: https://blog.csdn.net/u011857683/article/details/83758869

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

針對嵌入式人工智能,物聯(lián)網等專業(yè)技術分享和交流平臺,內容涉及arm,linux,android等各方面。