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

1 概述
 

最近業務上老有問題,查看發現overruns值不斷增加,學習了一下相關的知識。發現數值也在不停的增加。發現這些 errors, dropped, overruns 表示的含義還不大一樣。

[root@localhost ~]# ifconfig eth0
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
 

 

(1) RX errors

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

 

(2) RX dropped

表示數據包已經進入了 Ring Buffer,但是由於內存不夠等系統原因,導致在拷貝到內存的過程中被丟棄。

 

(3) RX overruns

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

 

(4) RX frame

表示 misaligned 的 frames。

 

 

 

 

 

 

 

2 網卡工作原理
 

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

 

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

 

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

 

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

 

 

 

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

 

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

 

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

 

 

 

2.3 網卡中斷處理函數
 

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

 

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

 

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

 

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

 

 

 

 

2.4 緩衝區訪問
網卡的內核緩衝區,是在PC內存中,由內核控制,而網卡會有FIFO緩衝區,或者ring buffer,這應該將兩者區分開。FIFO比較小,裏面有數據便會盡量將數據存在內核緩衝中。

 

網卡中的緩衝區既不屬於內核空間,也不屬於用戶空間。它屬於硬件緩衝,允許網卡與操作系統之間有個緩衝;

內核緩衝區在內核空間,在內存中,用於內核程序,做爲讀自或寫往硬件的數據緩衝區;

用戶緩衝區在用戶空間,在內存中,用於用戶程序,做爲讀自或寫往硬件的數據緩衝區;

另外,爲了加快數據的交互,可以將內核緩衝區映射到用戶空間,這樣,內核程序和用戶程序就可以同時訪問這一區間了。

 

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

 

 

 

 

 

 

3 丟包排查
網卡工作在數據鏈路層,數據量鏈路層,會做一些校驗,封裝成幀。我們可以查看校驗是否出錯,確定傳輸是否存在問題。然後從軟件層面,是否因爲緩衝區太小丟包。

 

 

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

(1) 查看工作模式是否正常

[root@localhost ~]# ethtool eth0 | egrep 'Speed|Duplex'
Speed: 1000Mb/s
Duplex: Full
 

(2) 查看檢驗是否正常

[root@localhost ~]# ethtool -S eth0 | grep crc
rx_crc_errors: 0
 
Speed,Duplex,CRC 之類的都沒問題,基本可以排除物理層面的干擾。

 

 

 

3.2 通過 ifconfig 可以看到 overruns 是否一直增大
 

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
 

 

 

3.3 查看buffer大小
 

可以通過ethtool來修改網卡的buffer size ,首先要網卡支持,我的服務器是是INTEL 的1000M網卡,我們看看ethtool說明 

-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.
 

(1) 查看當前網卡的buffer size情況

ethtool -g eth0
[root@localhost ~]# ethtool -g eth0
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
 

 

 

3.4 修改buffer size大小
ethtool -G eth0 rx 2048
 
ethtool -G eth0 tx 2048
 

[root@localhost ~]# ethtool -G eth0 rx 2048
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ethtool -G eth0 tx 2048
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ethtool -g eth0
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
 
--------------------- 
作者:路癡的旅行 
來源:CSDN 
原文:https://blog.csdn.net/u011857683/article/details/83758869 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章