pping: 被動式 ping,計算網絡時延

pping  是一個 Linux/macOS/BSD 命令行工具,它通過對活躍連接的被動監測來測量網絡延遲。

與  ping  不同,pping  不會注入流量 (主動發送探測包) 來確定 RTT(往返時間)——它報告的是正常應用流量所經歷的每個數據包的 RTT。與只能在發送端點測量 RTT 的傳輸狀態監控工具(如  ss)不同,pping  可以在發送方接收方或連接路徑上的任何位置測量 RTT(例如,OpenWrt 家庭邊界路由器可以輕鬆地監控所有進出互聯網流量的 RTT)。

ping 程序的原理主要是基於 ICMP 協議。具體來說,Ping 程序會向目標主機發送一個 ICMP Echo 請求數據包,並等待接收 Echo 迴應數據包。程序會按時間和成功響應的次數來估算丟失數據包率(丟包率)和數據包往返時間(網絡時延)。

ping 不同,pping 測量的是它所監控的數據包的往返延遲,即 TCP 連接兩端應用程序的往返時間。

如果 pping 與其中一個應用程序位於同一位置,它將測量通過本地協議棧和應用程序的延遲以及到通信主機的往返時間。如果位於路徑上,例如 WiFi 路由器或電纜調制解調器,則可以根據數據包捕獲的位置將主機端點之間的延遲進行分叉。與 ping 不同,pping 還會捕獲所有流經它的流,爲主機到各種互聯網連接提供可見性。與其他一些被動指標不同,pping 監控可以在連接的任何生命週期階段開始,即它不需要 SYN 數據包。

它的核心機制是通過看到 TCP 包中的 timestamp 選項中的 TS Value, 保存下來,反向看到相同的 TS Echo Reply 的值,認爲是相匹配的回包,計算兩個 TS Value 的差值作爲 RTT。

  • 雙方各自維護自己的時間戳,時間戳的值隨時間單調遞增(常見的更新頻率是 1ms 或 10ms)。

  • 當一方發送數據時,它會在 TCP 頭部的時間戳選項中設置當前的時間戳值(timestamp)。

  • 接收方在收到數據後,會在後續的 ACK 報文中的時間戳選項中設置timestamp echo字段爲接收到的timestamp值,並在timestamp字段中設置自己的當前時間戳。

  • 發送方通過比較發送時的時間戳和接收到的timestamp echo,可以計算出報文的往返時間(RTT)。

可以看到, pping 依賴包中的 timestamp 選項,如果不設置,則無法計算 RTT, 這也是它的一個限制。

它的代碼行數很少,核心函數 process_packet[1] 也就 150 行左右的代碼,對於我們學習網絡編程非常適合。

編譯

pping 依賴 libtins[2] 庫,所以你需要先安裝 libtins:

cd ~/src
git clone https://github.com/mfontanini/libtins.git
cd libtins
mkdir build
cd build
cmake ../ -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_CXX11=\
 -DLIBTINS_ENABLE_ACK_TRACKER=0 -DLIBTINS_ENABLE_WPA2=\
 -DCMAKE_INSTALL_PREFIX=`/usr/local`
make
make instal

然後 Clone pollere/pping[3] 修改 Makefile 文件:

# should only need to change LIBTINS to the libtins install prefix
# (typically /usr/local unless overridden when tins built)
LIBTINS = /usr/local
CPPFLAGS += -I$(LIBTINS)/include
LDFLAGS += -L$(LIBTINS)/lib  $(LIBTINS)/lib/libtins.a -lpcap
CXXFLAGS += -std=c++14 -g -O3 -Wall

pping:  pping.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o pping pping.cpp $(LDFLAGS)

clean:
rm pping

這裏我們使用的 libtins 的靜態庫,方便複製到其他機器上。

使用

pping 可以分析 pcap 的抓包文件,也可以實時的進行監控,選擇需要監控的網卡,還可以使用 tcpdump 一樣的過濾條件:![[Pasted image 20240513232003.png]]

第一列是抓包的時間,第二列是平均 RRT, 第三列是最小的 RTT,第四列是架空的五元組 (TCP)。

還有一些使用 XDP (ebpf) 實現的 pping, 比如 bpf-examples/pping[4],性能會更好,但是要求的 Linux 版本也高。

參考資料

[1]

process_packet: https://github.com/pollere/pping/blob/master/pping.cpp#L215

[2]

libtins: http://libtins.github.io/

[3]

pollere/pping: https://github.com/pollere/pping

[4]

bpf-examples/pping: https://github.com/xdp-project/bpf-examples/blob/master/pping/pping_kern.c

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/sOjUSvIM5IO-n0wL5KuIrQ?poc_token=HCJBQ2ajSKcc8EZ4JoXdq1e3GGn3kMQITQ91qQz-