Networking

分片和數據包大小,使用 tcpdump

  • May 17, 2013

我試圖理解碎片的概念:

我有兩個公共 IP 連接到交換機的虛擬機。

tracepath 顯示數據包不通過網關

從 vm1:嘗試將 65507 字節的 icmp 發送到 vm2。

ping -M want -s 65507 vm2 

但在 vm2 上的 tcpdump 輸出中:它的顯示

tcpdump -evvv icmp

12:48:44.635551 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 1480, flags [+], proto ICMP (1), length 1500)
VM1 > VM2: icmp
12:48:44.635568 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 2960, flags [+], proto ICMP (1), length 1500)
VM1 > Vm2: icmp
12:48:44.635572 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 4440, flags [+], proto ICMP (1), length 1500)
VM1>VM2 icmp
12:48:44.635575 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 5920, flags [+], proto ICMP (1), length 1500)
VM1>VM2: icmp
12:48:44.635578 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 7400, flags [+], proto ICMP (1), length 1500)
**Vm1 > VM2**: icmp
12:48:44.635581 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 8880, flags [+], proto ICMP (1), length 1500)

這將重複 31 次,直到完全接收。完整粘貼: http: //pastebin.com/cnQhn8dK

那麼為什麼看起來收到的總數據是1500*31=46500 bytes65507-46500=19007 bytes發生了什麼。

有人可以澄清一下嗎。

是的,使用帶有 -s 選項的 tcpdump,結果現在是正確的。作為您的結果,我們計算了 45 個數據包。44 個 1500 字節的數據包,1 個 415 字節的數據包。

44*1500 + 415 = 66415

66415 - 65507 = 908

908 / 45 = 20 加 8

可以看到,每個數據包為第一個數據包添加 20 個字節的 ip 標頭 + 8 個字節的 icmp 標頭。

只是為了補充Gnouc 的答案。

您正在發送65507數據字節。這不包括 8 字節的 ICMP 標頭。

最常見的 MTU 大小是1500. 這個大小占第 3 層大小,這就是為什麼您看到ethertype IPv4 (0x0800), length 1514:這意味著總幀大小實際上是 1514 字節。這 14 個字節佔乙太網報頭。每個 mac 地址 12 個字節 + 2 個類型。

IP 標頭的最小和非常常見的大小是其最小大小 20 字節(最大為 60 字節)。

所以我們有

1514 bytes - Ethernet header = 1500 bytes
1500 - IP header = 1480 bytes
1480 - ICMP header = 1472 bytes

您最多可以發送 1472 個字節而不會分片。

但是 IP 對數據包進行分段的方式不需要為每個數據包發送標頭,而只是為第一個數據包發送標頭。

在 MTU 為 1500 的情況下,您可以發送的最大字節數為 1480 字節。

我們知道您數據的總大小以及您可以發送的最大數據量。

所以至少需要65507 / 1480 ~= 44.2 packets. 即 1514 的 44 個數據包,然後是小於一半大小的最終數據包。

其餘的數據包發生了什麼?

但為什麼是 31 個數據包?好吧,這一切都在您正在擷取的緩衝區大小中。在您的 tcpdump 結束時,您應該看到

31 packets captured 
57 packets received by filter
14 packets dropped by kernel

如果您添加擷取的數據包+核心丟棄的數據包,您將得到正確的答案,這就是-s它改變快照長度的原因。

來自tcpdump 手冊

-s 從每個數據包中擷取 snaplen 字節的數據而不是預設的 65535 字節。由於快照受限而被截斷的數據包在輸出中用 `` 指示

$$ |proto $$’’,其中 proto 是發生截斷的協議級別的名稱。請注意,拍攝較大的快照既增加了處理數據包所需的時間,又有效地減少了數據包緩衝量。這可能會導致封包遺失。您應該將 snaplen 限制為將擷取您感興趣的協議資訊的最小數字。將 snaplen 設置為 0 會將其設置為預設值 65535,以便與最近的舊版本 tcpdump 向後兼容。

為什麼核心首先丟棄數據包?

再次來自 tcpdump 手冊頁

核心丟棄的數據包數(這是由於缺少緩衝區空間而被執行 tcpdump 的作業系統中的數據包擷取機制丟棄的數據包數,如果作業系統將該資訊報告給應用程序;如果沒有,它將報告為 0)。

引用自:https://serverfault.com/questions/508531