什麼是MTU?為什麼MTU值普遍都是1500?(轉)
原文地址:https://developer.aliyun.com/article/222535
感謝作者!
什麼是MTU
Maximum Transmission Unit,縮寫MTU,中文名是:最大傳輸單元。
這是哪一層網路的概念?
從下面這個表格中可以看到,在7層網路協議中,MTU是資料鏈路層的概念。MTU限制的是資料鏈路層的payload,也就是上層協議的大小,例如IP,ICMP等。
OSI中的層 | 功能 | TCP/IP協議族 |
---|---|---|
應用層 | 檔案傳輸,電子郵件,檔案服務,虛擬終端 | TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet |
表示層 | 資料格式化,程式碼轉換,資料加密 | 沒有協議 |
會話層 | 解除或建立與別的接點的聯絡 | 沒有協議 |
傳輸層 | 提供端對端的介面 | TCP,UDP |
網路層 | 為資料包選擇路由 | IP,ICMP,RIP,OSPF,BGP,IGMP |
資料鏈路層 | 傳輸有地址的幀以及錯誤檢測功能 | SLIP,CSLIP,PPP,ARP,RARP,MTU |
物理層 | 以二進位制資料形式在物理媒體上傳輸資料 | ISO2110,IEEE802,IEEE802.2 |
MTU有什麼用?
舉一個最簡單的場景,你在家用自己的筆記本上網,用的是路由器,路由器連線電信網路,然後訪問了www.baidu.com
,從你的筆記本出發的一個乙太網資料幀總共經過了以下路徑:
筆記本 -> 路由器 -> 電信機房 -> 伺服器
其中,每個節點都有一個MTU值,如下:
1500 1500 1500
筆記本 -> 路由器 -> 電信機房 -> 伺服器
假設現在我把筆記本的MTU最大值設定成了1700,然後傳送了一個超大的ip資料包(2000),這時候在以外網傳輸的時候會被拆成2個包,一個1700,一個300,然後加上頭資訊進行傳輸。
1700 1500 1500
筆記本 -> 路由器 -> 電信機房 -> 伺服器
路由器接收到了一個1700的幀,發現大於自己設定的最大值:1500,如果IP包DF標誌位為1,也就是不允許分包,那麼路由器直接就把這個包丟棄了,根本就不會到達電信機房,也就到不了伺服器了,所以,到這裡我們就會發現,MTU其實就是在每一個節點的管控值,只要是大於這個值的資料幀,要麼選擇分片,要麼直接丟棄。
為什麼是1500?
其實一個標準的乙太網資料幀大小是:1518
,頭資訊有14位元組,尾部校驗和FCS佔了4位元組,所以真正留給上層協議傳輸資料的大小就是:1518 - 14 - 4 = 1500,那麼,1518這個值又是從哪裡來的呢?
假設取一個更大的值
假設MTU值和IP資料包大小一致,一個IP資料包的大小是:65535,那麼加上乙太網幀頭和為,一個乙太網幀的大小就是:65535 + 14 + 4 = 65553
,看起來似乎很完美,傳送方也不需要拆包,接收方也不需要重組。
那麼假設我們現在的頻寬是:100Mbps
,因為乙太網幀是傳輸中的最小可識別單元,再往下就是0101所對應的光訊號了,所以我們的一條頻寬同時只能傳送一個乙太網幀。如果同時傳送多個,那麼對端就無法重組成一個乙太網幀了,在100Mbps
的頻寬中(假設中間沒有損耗),我們計算一下發送這一幀需要的時間:
( 65553 * 8 ) / ( 100 * 1024 * 1024 ) ≈ 0.005(s)
在100M網路下傳輸一幀就需要5ms,也就是說這5ms其他程序傳送不了任何資料。如果是早先的電話撥號,網速只有2M的情況下:
( 65553 * 8 ) / ( 2 * 1024 * 1024 ) ≈ 0.100(s)
100ms,這簡直是噩夢。其實這就像紅綠燈,時間要設定合理,交替通行,不然同一個方向如果一直是綠燈,那麼另一個方向就要堵成翔了。
既然大了不行,那設定小一點可以麼?
假設MTU值設定為100,那麼單個幀傳輸的時間,在2Mbps頻寬下需要:
( 100 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 ≈ 5(ms)
時間上已經能接受了,問題在於,不管MTU設定為多少,乙太網頭幀尾大小是固定的,都是14 + 4,所以在MTU為100的時候,一個乙太網幀的傳輸效率為:
( 100 - 14 - 4 ) / 100 = 82%
寫成公式就是:( T - 14 - 4 ) / T
,當T趨於無窮大的時候,效率接近100%
,也就是MTU的值越大,傳輸效率最高,但是基於上一點傳輸時間的問題,來個折中的選擇吧,既然頭加尾是18,那就湊個整來個1500,總大小就是1518,傳輸效率:
1500 / 1518 = 98.8%
100Mbps傳輸時間:
( 1518 * 8 ) / ( 100 * 1024 * 1024 ) * 1000 = 0.11(ms)
2Mbps傳輸時間:
( 1518 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 = 5.79(ms)
總體上時間都還能接受
最小值被限制在64
為什麼是64呢?
這個其實和乙太網幀在半雙工下的碰撞有關,感興趣的同學可以自行去搜索。
在我玩遊戲的時候,為什麼把MTU改成1480就不卡了?
路由器預設值大多都是1500,理論上是沒有問題的,那為什麼我玩遊戲的時候改成1480才能流暢呢?原因在於當時我使用的是ADSL上網的方式,ADSL使用的PPPoE協議。
PPPoE
PPPoE協議介於乙太網和IP之間,協議分為兩部分,PPP( Point to Point Protocol )和oE( over Ethernet ),也就是乙太網上的PPP協議,而PPPoE協議頭資訊為:
| VER(4bit) | TYPE(4bit) | CODE(8bit) | SESSION-ID(16bit) | LENGTH(16bit) |
這裡總共是48位,也就是6個位元組,那麼另外2個位元組是什麼呢?答案是PPP協議的ID號,佔用兩個位元組,所以在PPPoE環境下,最佳MTU值應該是:1500 - 4 - 2 = 1492。
我的上網方式
當時我的上網路徑如下:
PC -> 路由器 -> 電信
我在路由器進行撥號,然後PC連線路由器進行上網。
最根本原因
問題就出在路由器撥號,如果是PC撥號,那麼PC會進行PPPoE的封裝,會按照MTU:1492來進行乙太網幀的封裝,即使通過路由器,路由器這時候也只是轉發而已,不會進行拆包。
而當用路由器撥號時,PC並不知道路由器的通訊方式,會以網絡卡的設定,預設1500的MTU來進行乙太網幀的封裝,到達路由器時,由於路由器需要進行PPPoE協議的封裝,加上8位元組的頭資訊,這樣一來,就必須進行拆包,路由器把這一幀的內容拆成兩幀傳送,一幀是1492,一幀是8,然後分別加上PPPoE的頭進行傳送。
平時玩遊戲不卡,是因為資料量路由器還處理得過來,而當進行群怪AOE的時候,由於短時間資料量過大,路由器處理不過來,就會發生丟包卡頓的情況,也就掉線了。
帖子裡面提到的1480,猜測可能是儘量設小一點,避免二次撥號帶來的又一次PPPoE的封裝,因為時間久遠,沒辦法回到當時的場景再去抓包了。
結論
1518這個值是考慮到傳輸效率以及傳輸時間而折中選擇的一個值,並且由於目前網路鏈路中的節點太多,其中某個節點的MTU值如果和別的節點不一樣,就很容易帶來拆包重組的問題,甚至會導致無法傳送。