分片和數據包大小,使用 tcpdump
我試圖理解碎片的概念:
我有兩個公共 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 bytes而65507-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
它改變快照長度的原因。-s 從每個數據包中擷取 snaplen 字節的數據而不是預設的 65535 字節。由於快照受限而被截斷的數據包在輸出中用 `` 指示
$$ |proto $$’’,其中 proto 是發生截斷的協議級別的名稱。請注意,拍攝較大的快照既增加了處理數據包所需的時間,又有效地減少了數據包緩衝量。這可能會導致封包遺失。您應該將 snaplen 限制為將擷取您感興趣的協議資訊的最小數字。將 snaplen 設置為 0 會將其設置為預設值 65535,以便與最近的舊版本 tcpdump 向後兼容。
為什麼核心首先丟棄數據包?
再次來自 tcpdump 手冊頁
核心丟棄的數據包數(這是由於缺少緩衝區空間而被執行 tcpdump 的作業系統中的數據包擷取機制丟棄的數據包數,如果作業系統將該資訊報告給應用程序;如果沒有,它將報告為 0)。