最近工作中遇到某個(gè)服務(wù)器應(yīng)用程序 UDP 丟包,在排查過程中查閱了很多資料,總結(jié)出來(lái)這篇文章,供更多人參考。
在開始之前,我們先用一張圖解釋 linux 系統(tǒng)接收網(wǎng)絡(luò)報(bào)文的過程。
- 首先網(wǎng)絡(luò)報(bào)文通過物理網(wǎng)線發(fā)送到網(wǎng)卡
- 網(wǎng)絡(luò)驅(qū)動(dòng)程序會(huì)把網(wǎng)絡(luò)中的報(bào)文讀出來(lái)放到 ring buffer 中,這個(gè)過程使用 DMA(Direct Memory Access),不需要 CPU 參與
- 內(nèi)核從 ring buffer 中讀取報(bào)文進(jìn)行處理,執(zhí)行 IP 和 TCP/UDP 層的邏輯,最后把報(bào)文放到應(yīng)用程序的 socket buffer 中
- 應(yīng)用程序從 socket buffer 中讀取報(bào)文進(jìn)行處理
在接收 UDP 報(bào)文的過程中,圖中任何一個(gè)過程都可能會(huì)主動(dòng)或者被動(dòng)地把報(bào)文丟棄,因此丟包可能發(fā)生在網(wǎng)卡和驅(qū)動(dòng),也可能發(fā)生在系統(tǒng)和應(yīng)用。
之所以沒有分析發(fā)送數(shù)據(jù)流程,一是因?yàn)榘l(fā)送流程和接收類似,只是方向相反;另外發(fā)送流程報(bào)文丟失的概率比接收小,只有在應(yīng)用程序發(fā)送的報(bào)文速率大于內(nèi)核和網(wǎng)卡處理速率時(shí)才會(huì)發(fā)生。
本篇文章假定機(jī)器只有一個(gè)名字為 eth0
的 interface,如果有多個(gè) interface 或者 interface 的名字不是 eth0,請(qǐng)按照實(shí)際情況進(jìn)行分析。
NOTE:文中出現(xiàn)的 RX
(receive) 表示接收?qǐng)?bào)文,TX
(transmit) 表示發(fā)送報(bào)文。
確認(rèn)有 UDP 丟包發(fā)生
要查看網(wǎng)卡是否有丟包,可以使用 ethtool -S eth0
查看,在輸出中查找 bad
或者 drop
對(duì)應(yīng)的字段是否有數(shù)據(jù),在正常情況下,這些字段對(duì)應(yīng)的數(shù)字應(yīng)該都是 0。如果看到對(duì)應(yīng)的數(shù)字在不斷增長(zhǎng),就說(shuō)明網(wǎng)卡有丟包。
另外一個(gè)查看網(wǎng)卡丟包數(shù)據(jù)的命令是 ifconfig
,它的輸出中會(huì)有 RX
(receive 接收?qǐng)?bào)文)和 TX
(transmit 發(fā)送報(bào)文)的統(tǒng)計(jì)數(shù)據(jù):
ifconfig eth0
...
RX packets 3553389376 bytes 2599862532475 (2.3 TiB)
RX errors 0 dropped 1353 overruns 0 frame 0
TX packets 3479495131 bytes 3205366800850 (2.9 TiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
此外,linux 系統(tǒng)也提供了各個(gè)網(wǎng)絡(luò)協(xié)議的丟包信息,可以使用 netstat -s
命令查看,加上 --udp
可以只看 UDP 相關(guān)的報(bào)文數(shù)據(jù):
GOD]# netstat -s -u
IcmpMsg:
InType0: 3
InType3: 1719356
InType8: 13
InType11: 59
OutType0: 13
OutType3: 1737641
OutType8: 10
OutType11: 263
Udp:
517488890 packets received
2487375 packets to unknown port received.
47533568 packet receive errors
147264581 packets sent
12851135 receive buffer errors
0 send buffer errors
UdpLite:
IpExt:
OutMcastPkts: 696
InBcastPkts: 2373968
InOctets: 4954097451540
OutOctets: 5538322535160
OutMcastOctets: 79632
InBcastOctets: 934783053
InNoECTPkts: 5584838675
對(duì)于上面的輸出,關(guān)注下面的信息來(lái)查看 UDP 丟包的情況:
packet receive errors
不為空,并且在一直增長(zhǎng)說(shuō)明系統(tǒng)有 UDP 丟包packets to unknown port received
表示系統(tǒng)接收到的 UDP 報(bào)文所在的目標(biāo)端口沒有應(yīng)用在監(jiān)聽,一般是服務(wù)沒有啟動(dòng)導(dǎo)致的,并不會(huì)造成嚴(yán)重的問題receive buffer errors
表示因?yàn)?UDP 的接收緩存太小導(dǎo)致丟包的數(shù)量
NOTE:并不是丟包數(shù)量不為零就有問題,對(duì)于 UDP 來(lái)說(shuō),如果有少量的丟包很可能是預(yù)期的行為,比如丟包率(丟包數(shù)量/接收?qǐng)?bào)文數(shù)量)在萬(wàn)分之一甚至更低。
網(wǎng)卡或者驅(qū)動(dòng)丟包
之前講過,如果 ethtool -S eth0
中有 rx_***_errors
那么很可能是網(wǎng)卡有問題,導(dǎo)致系統(tǒng)丟包,需要聯(lián)系服務(wù)器或者網(wǎng)卡供應(yīng)商進(jìn)行處理。
# ethtool -S eth0 | grep rx_ | grep errors
rx_crc_errors: 0
rx_missed_errors: 0
rx_long_length_errors: 0
rx_short_length_errors: 0
rx_align_errors: 0
rx_errors: 0
rx_length_errors: 0
rx_over_errors: 0
rx_frame_errors: 0
rx_fifo_errors: 0
netstat -i
也會(huì)提供每個(gè)網(wǎng)卡的接發(fā)報(bào)文以及丟包的情況,正常情況下輸出中 error 或者 drop 應(yīng)該為 0。
如果硬件或者驅(qū)動(dòng)沒有問題,一般網(wǎng)卡丟包是因?yàn)樵O(shè)置的緩存區(qū)(ring buffer)太小,可以使用 ethtool
命令查看和設(shè)置網(wǎng)卡的 ring buffer。
ethtool -g
可以查看某個(gè)網(wǎng)卡的 ring buffer,比如下面的例子
# ethtool -g eth0
Ring parameters for eth0:
maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 256
RX Mini: 0
RX Jumbo: 0
TX: 256
Pre-set 表示網(wǎng)卡最大的 ring buffer 值,可以使用 ethtool -G eth0 rx 8192
設(shè)置它的值。
Linux 系統(tǒng)丟包
linux 系統(tǒng)丟包的原因很多,常見的有:UDP 報(bào)文錯(cuò)誤、防火墻、UDP buffer size 不足、系統(tǒng)負(fù)載過高等,這里對(duì)這些丟包原因進(jìn)行分析。
UDP 報(bào)文錯(cuò)誤
如果在傳輸過程中UDP 報(bào)文被修改,會(huì)導(dǎo)致 checksum 錯(cuò)誤,或者長(zhǎng)度錯(cuò)誤,linux 在接收到 UDP 報(bào)文時(shí)會(huì)對(duì)此進(jìn)行校驗(yàn),一旦發(fā)明錯(cuò)誤會(huì)把報(bào)文丟棄。
如果希望 UDP 報(bào)文 checksum 及時(shí)有錯(cuò)也要發(fā)送給應(yīng)用程序,可以在通過 socket 參數(shù)禁用 UDP checksum 檢查:
int disable = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)
原文:https://cizixs.com/2018/01/13/linux-udp-packet-drop-debug/
-
cpu
+關(guān)注
關(guān)注
68文章
11069瀏覽量
216717 -
Linux
+關(guān)注
關(guān)注
87文章
11506瀏覽量
213421 -
dma
+關(guān)注
關(guān)注
3文章
576瀏覽量
103008 -
網(wǎng)絡(luò)驅(qū)動(dòng)
+關(guān)注
關(guān)注
0文章
7瀏覽量
7496
發(fā)布評(píng)論請(qǐng)先 登錄
udp數(shù)據(jù)丟包的原因?
共享控制系統(tǒng)的丟包預(yù)測(cè)補(bǔ)償控制算法
網(wǎng)絡(luò)數(shù)據(jù)丟包的原因及攝像機(jī)丟包的原因
Linux應(yīng)用的延時(shí)和丟包模擬
網(wǎng)絡(luò)丟包時(shí)常用的排錯(cuò)思路
Linux優(yōu)化實(shí)戰(zhàn):如何分析網(wǎng)絡(luò)丟包的問題
深入分析Linux網(wǎng)絡(luò)丟包問題!
深入分析Linux網(wǎng)絡(luò)丟包問題

簡(jiǎn)述linux系統(tǒng)UDP丟包問題分析思路(下)
如何解決MPSoC萬(wàn)兆以太網(wǎng)應(yīng)用中UDP接收丟包問題

Linux下模擬網(wǎng)絡(luò)時(shí)延和丟包神器介紹

網(wǎng)絡(luò)丟包故障如何定位

網(wǎng)絡(luò)丟包問題分析

評(píng)論