linux 丢包排查思路简述(tcp+rdma)
linux 丟包排查思路簡述
- 概述
- 網絡包接收流程
- 網絡包發送流程
- 丟包排查的思路
- tcp排查方法
- rdma排查方法
- 網絡工具匯總
- 參考鏈接
概述
我們首先以tcp網絡為例,談談linux系統如何收發網絡包
在進行網絡傳輸時,數據包就會按照協議棧,對上一層發來的數據進行逐層處理;然后封裝上該層的協議頭,再發送給下一層。
- 傳輸層在應用程序數據前面增加了 TCP 頭;
- 網絡層在 TCP 數據包前增加了 IP 頭;
- 而網絡接口層,又在 IP 數據包前后分別增加了幀頭和幀尾。
這些新增的頭部和尾部,都按照特定的協議格式填充,想了解具體格式,你可以查看協議的文檔。
比如,你可以查看這里,了解 TCP 頭的格式。這些新增的頭部和尾部,增加了網絡包的大小,但我們都知道,物理鏈路中并不能傳輸任意大小的數據包。網絡接口配置的最大傳輸單元(MTU),就規定了最大的 IP 包大小。在我們最常用的以太網中,MTU 默認值是 1500(這也是 Linux 的默認值)。一旦網絡包超過 MTU 的大小,就會在網絡層分片,以保證分片后的 IP 包不大于 MTU 值。顯然,MTU 越大,需要的分包也就越少,自然,網絡吞吐能力就越好。
如下圖所示,就是 Linux 通用 IP 網絡棧的示意圖:(圖片參考《性能之巔》圖 10.7 通用 IP 網絡棧繪制)
我們從上到下來看這個網絡棧,可以發現,
- 最上層的應用程序,需要通過系統調用,來跟套接字接口進行交互;
- 套接字的下面,就是我們前面提到的傳輸層、網絡層和網絡接口層;
- 最底層,則是網卡驅動程序以及物理網卡設備。
網卡,作為發送和接收網絡包的基本設備。在系統啟動過程中,網卡通過內核中的網卡驅動程序注冊到系統中。而在網絡收發過程中,內核通過中斷跟網卡進行交互。再結合前面提到的 Linux 網絡棧,可以看出,網絡包的處理非常復雜。所以,網卡硬中斷只處理最核心的網卡數據讀取或發送,而協議棧中的大部分邏輯,都會放到軟中斷中處理。(如果top時發現系統的si比較高,可以通過定位/proc/softirqs中增長較快的軟中斷從而定位問題。)
理解了上述架構,我們就不難理解,為什么tcp的收發過程會牽涉到如下幾個緩沖區:
- 網卡收發網絡包時,通過 DMA 方式交互的環形緩沖區;
- 網卡中斷處理程序為網絡幀分配的,內核數據結構 sk_buff 緩沖區;
- 應用程序通過套接字接口,與網絡協議棧交互時的套接字緩沖區。
網絡包接收流程
- 在鏈路層檢查報文的合法性,找出上層協議的類型(比如 IPv4 還是 IPv6),再去掉幀頭、幀尾,然后交給網絡層。
- 網絡層取出 IP 頭,判斷網絡包下一步的走向,比如是交給上層處理還是轉發。當網絡層確認這個包是要發送到本機后,就會取出上層協議的類型(比如 TCP 還是 UDP),去掉 IP 頭,再交給傳輸層處理。
- 傳輸層取出 TCP 頭或者 UDP 頭后,根據 < 源 IP、源端口、目的 IP、目的端口 > 四元組作為標識,找出對應的 Socket,并把數據拷貝到 Socket 的接收緩存中。
網絡包發送流程
了解網絡包的接收流程后,就很容易理解網絡包的發送流程。網絡包的發送流程就是上圖的右半部分,很容易發現,網絡包的發送方向,正好跟接收方向相反。
丟包排查的思路
理解了linux網絡棧的原理,我們就不難去定位丟包問題,
關于丟包及其分析設計網絡棧、內核棧的各個層面,筆者在也僅僅稍懂皮毛,歡迎讀者踴躍補充。
我們可以使用ifconfig可以查看網絡丟包情況
$ ifconfig net0 net0: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST> mtu 1500ether 98:03:9b:8c:63:3a txqueuelen 1000 (Ethernet)RX packets 46725983 bytes 9200932091 (8.5 GiB)RX errors 0 dropped 48193 overruns 0 frame 0TX packets 127710842 bytes 127005910250 (118.2 GiB)TX errors 1 dropped 0 overruns 0 carrier 1 collisions 0- RX errors: 表示總的收包的錯誤數量,這包括 too-long-frames 錯誤,Ring Buffer 溢出錯誤,crc 校驗錯誤,幀同步錯誤,fifo overruns 以及 missed pkg 等等。
- RX dropped: 表示數據包已經進入了 Ring Buffer,但是由于內存不夠等系統原因,導致在拷貝到內存的過程中被丟棄。
- RX overruns: 表示了 fifo 的 overruns,這是由于 Ring Buffer(aka Driver Queue) 傳輸的 IO 大于 kernel 能夠處理的 IO 導致的,而 Ring Buffer 則是指在發起 IRQ 請求之前的那塊 buffer。很明顯,overruns 的增大意味著數據包沒到 Ring Buffer 就被網卡物理層給丟棄了,而 CPU 無法即使的處理中斷是造成 Ring Buffer 滿的原因之一
- RX frame: 表示 misaligned 的 frames。
對于 TX 的來說,出現上述 counter 增大的原因主要包括 aborted transmission, errors due to carrirer, fifo error, heartbeat erros 以及 windown error,而 collisions 則表示由于 CSMA/CD 造成的傳輸中斷。
dropped與overruns的區別:
- dropped,表示這個數據包已經進入到網卡的接收緩存fifo隊列,并且開始被系統中斷處理準備進行數據包拷貝(從網卡緩存fifo隊列拷貝到系統內存),但由于此時的系統原因(比如內存不夠等)導致這個數據包被丟掉,即這個數據包被Linux系統丟掉。
- overruns,表示這個數據包還沒有被進入到網卡的接收緩存fifo隊列就被丟掉,因此此時網卡的fifo是滿的。為什么fifo會是滿的?因為系統繁忙,來不及響應網卡中斷,導致網卡里的數據包沒有及時的拷貝到系統內存,fifo是滿的就導致后面的數據包進不來,即這個數據包被網卡硬件丟掉。所以,個人覺得遇到overruns非0,需要檢測cpu負載與cpu中斷情
tcp排查方法
tcp丟包排查方法和工具集比較健全,手段也比較多,一般情況下,我們分析tcp丟包主要分析出向丟包重傳,通過在出向丟包的服務器上抓包,找到出問題的網絡包和對端服務器。
這里僅舉幾個例子:
- wireshark抓重傳包的原理是:由于tcp字段中沒有重傳相關的資源,因此wireshark通過掃描網絡包中SEQ/ACK number, IP ID, source and destination IP address, TCP Port等字段,找到重復包,這些包就是丟包重傳的包。
rdma排查方法
目前我遇到的系統(mlx cx4/cx5/cx6),在rdma上主要的指標是入向丟包(out_of_order),其根因有如下幾種情況:
- 打開roce v2的tcpdump支持ethtool --set-priv-flags net0 sniffer on(注意,使用完成之后記得關閉ethtool --set-priv-flags net0 sniffer off)
- 使用tcpdump進行抓包,在wireshark中使用過濾器ip.dsfield.dscp,過濾出dscp錯誤的rdma包。如果存在,說明有dscp入錯隊列的rdma流量。
- 也可以在抓包的時候使用參數過濾,如:tcpdump -i net2 '(ip and (ip[1] & 0xfc) >> 2 != 46)' -w rdma_retrans.pcap,該語句過濾掉了dscp等于46的網絡包。
- 抓到包后我們就知道了問題流量的src和dest在哪里,我們可以通過perftest(如ib_send_bw)工具打流確認。
網絡工具匯總
tcp
rdma
RoCE/RDMA Tools
參考鏈接
總結
以上是生活随笔為你收集整理的linux 丢包排查思路简述(tcp+rdma)的全部內容,希望文章能夠幫你解決所遇到的問題。