在 tcpdump 記錄中未看到 Tc qdisc 延遲
我有兩個用 veth 對連接的 linux 容器。在一個容器的 veth-interface 上,我設置了 tc qdisc netem 延遲並將流量從它發送到另一個容器。如果我使用 tcpdump/wireshark 觀察雙方的流量,可以看出發送方和接收方的同一數據包的時間戳不會因所選延遲而有所不同。
我想更詳細地了解 libpcap 將時間戳放入對應於 tc qdisc 的出口流量。我在網際網路上搜尋了一個方案/圖像,但沒有找到。我找到了這個主題(wireshark 數據包擷取點),但它建議通過多一個容器/介面來引入間接性。在我的情況下,這不是一個可能的解決方案。有沒有什麼方法可以解決這個問題,而不是引入額外的中間介面(即不改變拓撲),只通過在已經給定的 veth-interface 上記錄但以可以看到延遲的方式來解決這個問題?
更新:
我太快了,所以弄錯了。我的解決方案(與@AB 的答案的第一個變體相同)和@AB 的 IFB 解決方案(我已經檢查過)都不能解決我的問題。
a1-eth0
問題是拓撲中發送方介面的傳輸隊列溢出:[a1-br0 ---3Gbps---a1-eth0]---100Mbps---r1---100Mbps---r2
我太快了,只檢查了
a1-eth0
和 router之間連結的延遲 10msr1
。今天我試圖讓延遲更高:100 毫秒、200 毫秒,結果(我得到的每個數據包延遲和速率圖)對於上面的拓撲和普通拓撲開始有所不同:[a1-eth0]---100Mbps---r1---100Mbps---r2
所以不,當然,對於準確的測試,我不能有額外的連結:Linux 橋、這個 IFB 和任何其他第三方系統都沒有引入。我測試擁塞控制方案。我想在一個特定的拓撲中做到這一點。而且我不能僅僅為了繪圖而改變拓撲——我的意思是,如果我的速率和延遲結果/圖同時發生變化。
更新 2:
所以看起來解決方案已經找到了,如下圖所示(NFLOG解決方案)。
更新 3:
這裡描述了 NFLOG 解決方案的一些缺點(大的 Link-Layer 標頭和錯誤的 TCP 校驗和用於零負載的出口 TCP 數據包)並提出了一個更好的解決方案,使用 NFQUEUE 沒有任何這些問題:零長度出口數據包的 TCP 校驗和錯誤(使用 iptables 擷取)。然而,對於我的任務(測試擁塞控制方案),NFLOG 和 NFQUEUE 都不適合。正如同一個連結所解釋的,當從核心的 iptables 擷取數據包時,發送速率會受到限制(這就是我的理解)。因此,當您通過從介面擷取(即定期)在發送方進行記錄時,您將獲得 2 GB 轉儲,而如果您通過從 iptables 擷取在發送方進行記錄,您將獲得 1 GB 轉儲。粗略地講。
更新 4:
最後,在我的項目中,我使用了我自己的答案中描述的 Linux 橋接解決方案。
根據Netfilter 和 General Networking示意圖中的數據包流,tcpdump在egress ( qdisc ) 之後擷取 ( AF_PACKET ) 。所以在 tcpdump 中看不到延遲是正常的:延遲在初始擷取時已經存在。
您必須提前一步擷取它,因此涉及第三個系統:
S1:system1,在傳出介面上執行 tcpdump
R:路由器(或網橋,在您方便時,這不會改變任何內容),執行 qdisc netem
S2:system2,在傳入介面上執行 tcpdump
__________________ ________________ __________________ | | | | | | | (S1) -- tcpdump -+---+- (R) -- netem -+---+- tcpdump -- (S2) | |__________________| |________________| |__________________|
這意味著涉及 3 個網路堆棧,它們是真實的、vm、網路命名空間(包括ip netns、LXC、…)
或者,也可以通過使用帶有鏡像流量的 IFB 介面來欺騙和移動路由器(或網橋)上的每個特殊設置*:*允許通過一個技巧(專用於這種情況)插入 netem 排序後的入口而不是 on出口:
_______ ______________________________________________ _______ | | | | | | | (S1) -+---+- tcpdump -- ifb0 -- netem -- (R) -- tcpdump -+---+- (S2) | |_______| |______________________________________________| |_______|
*tc mirred 手冊*頁中有一個基本的 IFB 用法範例:
使用 ifb 介面,可以通過 sfq 的實例發送入口流量:
# modprobe ifb # ip link set ifb0 up # tc qdisc add dev ifb0 root sfq # tc qdisc add dev eth0 handle ffff: ingress # tc filter add dev eth0 parent ffff: u32 \ match u32 0 0 \ action mirred egress redirect dev ifb0
只需在*ifb0*上使用 netem 而不是 sfq (在非初始網路命名空間中,
ip link add name ifbX type ifb
工作正常,沒有 modprobe)。這仍然需要 3 個網路堆棧才能正常工作。
使用NFLOG
根據 JenyaKh 的建議,事實證明可以使用tcpdump在出口之前(因此在 qdisc 之前)然後在出口(在 qdisc 之後)擷取數據包:通過使用iptables(或*nftables)將完整數據包記錄到 netlink 日誌基礎設施,並且仍然使用tcpdump讀取它們,然後在出口介面上再次使用tcpdump 。*這僅需要 S1 上的設置(不再需要路由器/網橋)。
因此,在 S1 上使用iptables,類似於:
iptables -A OUTPUT -o eth0 -j NFLOG --nflog-group 1
可能應該添加特定的過濾器以匹配完成的測試,因為tcpdump過濾器僅限於 nflog 介面(wireshark 應該更好地處理它)。
如果需要擷取答案(此處在不同的組中完成,因此需要額外的tcpdump):
iptables -A INPUT -i eth0 -j NFLOG --nflog-group 2
根據需要,也可以將它們移至raw/OUTPUT和raw/PREROUTING。
使用tcpdump:
# tcpdump -i nflog:1 -n -tt ...
如果使用不同的組 (= 2) 進行輸入:
# tcpdump -i nflog:2 -n -tt ...
然後像往常一樣同時:
# tcpdump -i eth0 -n -tt ...