作者:一天 首發公眾號:網路之路部落格(ID:NetworkBlog)
MTU與IP分片(可選內容瞭解)
這裡來講一個比較有趣的內容,相信大家都有設定過家用路由器的經歷,不知道有沒有發現一個事情,在設定撥號的時候,裡面有一個MTU,值通常是1492或者1480,如果接入方式改為DHCP的情況下,MTU就變成了1500,為什麼呢?
(1)瞭解MTU的作用
Maximum Transmission Unit(MTU):最大傳輸單元。還是以上面的例子,為什麼路由器撥號的時候要把MTU設定成1492呢?在這之前已經知道了乙太網頭部,一個標準的乙太網資料幀最大為1518,其中源MAC 6位元組,目的MAC 6個位元組,Type 2個位元組,FCS 4個位元組(前導碼不算在內,在物理層就已經去掉了),6+6+2+4=18個位元組,1518-18=1500,這1500正好是是留給上層協議傳輸的大小,也就是我們說的資料幀的大小是1500個位元組,包括IP頭部以及上層協議與資料整體在內,也就是說在二層乙太網中,實際能傳輸的資料是1500個位元組。
舉一個最常見的例子,我們平時在家裡用手機或者筆記本連線家用路由器看電視劇、刷抖音,資料包都是這樣的路徑,每個節點都有對應的MTU值,正常都為1500.
假設某一天,外網的對接方式變了,變成了撥號的形式,正常設定後,發現開啟網頁很慢或者打不開,諮詢路由器客服後,把MTU值改成1492或者更小點,驚奇的事情發生了,都能正常訪問了,這就回到之前的問題了,為什麼現在的路由器MTU都會設定成1492呢?
那是因為寬頻撥號使用的協議是PPPoE,由於還沒涉及這一塊的知識點,我們在這知道它佔用8個位元組就行,並且是封裝在乙太網中的。比如訪問者傳送了一個1495位元組的資料包給影片伺服器,但是由於家用路由器採用的是這就在原來1500的位元組上多出來了8個位元組,超過了標準的MTU值1500位元組,所以這個時候家用路由器會將這個資料包進行分片,分為2個,一個為資料包為1500個位元組,另外一個數據包為3個位元組,到了伺服器這邊在進行重組。(實際會更加複雜點,待會我們來做個小實驗)
(2)IP分片帶來的問題
IP分片其實在網路中是一種比較糟糕的情況,帶來了幾個問題
- 傳輸效率降低:分片會降低傳輸效率(這個待會我們用簡單的實驗可以看到)
- 增加裝置的壓力:原本一個數據包大小正好在1500位元組的範圍內,直接就傳送了,如果超過了1500個位元組,就需要涉及到分片,如果這種資料包一多,對應的裝置壓力就會增大,佔用裝置的資源。
- 延遲加大:分片另外一個問題就是當同一個資料包的多個分片抵達目的地後,目的終端需要將資料包重組排列後才能夠去讀取裡面的內容。好比一個大的物件被拆分成多個小的物件傳送出去,接收後,需要進行重新組裝,更糟糕的是萬一某一個元件晚到,那麼其他到了的元件就得等待;在IP分片重組中也是這樣的,所以會導致延遲加大。
- 丟包:更嚴重的是,在複雜的網路環境中,萬一某一個分片丟失了,那其餘接收到的資料就沒任何意義了,組不成一個完整的資料包,從而被丟棄。
- 某些應用訪問失效:比如上面的網頁開啟失敗或者很慢就是因為分片造成的,有的伺服器有保護措施,拒絕接收分片的資料包。
(3)為什麼MTU是1500呢,明明IP欄位的總長度是65535?
之前學過IP頭部的內容,IP頭部裡面有一個總長度,最大值是65535,表示IP協議是能夠承載這麼大資料包的,但是由於乙太網的資料部分最大為1500,所以你在很多書籍或者稱呼裡面會看到IP的資料包最大是1500個位元組,多了就會被分片,那為什麼乙太網要把資料部分定在1500,不能跟IP頭部一樣用65535嗎?那效率不是高很多。
- 乙太網最小位元組為什麼要求是64呢?
最早的乙太網是工作在共享網路下的,任何一個終端節點發送資料之前,都需要偵聽線路上是否有資料在傳,如果有,需要等待,如果發現線路可用,才可以傳送。假設A與B終端同時傳輸1個bit給對方的話,會產生衝突,其中一個就需要等待一端傳送完成後在過一個時間間隙才能傳送,這個時間間隙是57.6μs。
在10Mbps的乙太網中,在57.6μs時間內,能夠傳輸576個bit,乙太網中要求資料幀最小長度為576個bit,原因是這個長度正好能夠讓最極端的衝突環境都能夠被檢測到(CSMA/CD),而576個bit換算成位元組是72,去掉8個位元組的前導符,正好是64個位元組,這也是乙太網幀資料部分要求的最小長46的原因(46+18),不夠46的會自動填充。
- MTU值為什麼是1500
這個是瞭解64位元組的由來,是因為早期工作方式的原因(CSMA/CD),那1500位元組又是什麼原因呢?
假設乙太網沒有這個限制,IP協議最大可以承載65535位元組,加上乙太網頭部和尾部,是65535+14+4=65553位元組,如果早期在10Mbps的乙太網上傳輸,會佔用共享鏈路50ms,這樣嚴重影響了其他主機的通訊,如果有延遲敏感的應用,那肯定是無法接收的,另外如果線路的質量差,大包引起的丟包機率也會大很多。(50ms的計算方法:(65553*8)/(10*1024*1024)≈0.05(s)(小知識點科普:Mbps為每秒傳輸百萬位位元,而65535是位元組單位,1位元組=8位元,所以需要*8,10Mbps換算成bps就是10*1024*1024))
竟然大的不行,換成小的呢?,比如MTU等於100,就拿上面學過的ICMP的Ping來說,如果乙太網長度為100,ICMP實際資料= 100-ICMP頭部(8個位元組)-IP頭部(20個位元組)-乙太網頭部(18個位元組)=100-8-20-18=54,你會發現有效率實在太低了,有效率=54/100=54%
最終得到一個透過層層計算,發現如果乙太網長度為1518的時候,有效傳輸效率=1472/1518=96.9%,這個值既能保證有一個較大的幀長度,又保證了有效傳效率。更大的或者更小的就會出現上述的問題,這個也是一個折中的長度:1518位元組,對應上層IP 就是1500位元組(1518-18),這個就是最大傳輸單元MTU的由來。
- 為什麼不改善這個問題呢?
出現這個問題是因為早期乙太網透過Hub這些裝置工作,處於共享方式,效率很低,而現在的網路早已不是10M的網路了,交換機已經支援1G,10G、100G,而且頻寬獨享,可以同時收發的特性,那有效傳輸效率跟質量提升了非常多,但是如今的網路你會發現常見的還是用的mtu 1500的標準,只有資料中心或者某些特殊環境使用了一個叫做巨型幀 Jumbo Frame,可以支援大於9000位元組的大小,如果全網都使用這種,那傳輸大的檔案這些不是更快、延遲很小嗎?
但是現實環境沒這麼簡單,因為MTU在每個裝置的每一個介面(網絡卡)上面都是存在的
如果訪問者支援MTU 9000,傳送了一個9000大小的資料包交給無線路由器,無線路由正好也支援這麼大,交給網際網路裝置,網際網路中裝置非常多,並不是所有裝置都能夠去支援巨型幀的特性,很多地方還使用的非常老的裝置在執行,如果要支援勢必是大面積更換,成本會非常大,那如果一個數據包9000大小經過一個MTU是標準1500的裝置,那勢必就會造成分片了,還有許多比如超長幀會造成延時、CRC錯誤變多等問題,導致至今無法大面積普及使用的主要原因。
(4)IP分片後為什麼會造成延遲跟效率低呢?
拖兩臺電腦,分別設定好地址,然後抓包來看看分片的情況。
說下命令,Ping 192.168.255.2這個都能夠知道啥意思,-l表示ICMP的資料部分(不含其它任何頭部資訊)為1473,-c 1只發送一次。
透過抓包,可以看到有幾個資訊(wireshark升級了下,介面看起來更美觀了~)
- ARP:這個是獲取對方IP對應的MAC
- ICMP,這個是正常的ICMP協議的報文
- IP Fragmented:IP分片包
有IP分片包出現,說明剛剛的資料包整體超過1500個位元組了。
- 資料明明是1473怎麼就超過1500位元組了呢?
這裡要注意,1473表明的是ICMP資料部分的大小,不計算頭部在內,那麼加上頭部後呢? 1473+8(ICMP頭部)+20(IP頭部)=1501,這樣正好超過了1500個位元組,所以導致分片了。MTU是二層概念,二層以上的頭部加資料不能超過1500,否則會進行分片。
- 從192.168.255.1到192.168.255.2為什麼只有一個分片包
這裡對於剛接觸抓包的朋友來說,可能有點看不懂,我們來看幾個引數
- IP頭部裡面有一個identification 這個是識別符號,分片的包會打上相同的包,方便目的端區分
- Flags裡面的MF位是1,表示這個不是最後一個包,如果是最後一個包會為0
- offset:偏移符,表示資料包的位置,這個為0,表示是第一個分片包
- Data:你這裡會發現數據是1480,並且是沒有ICMP頭部的(這個內容其實是包含了頭部資訊的,1480-8,1472,注意:只有第一個分片會攜帶頭部資訊,抓包沒有顯示出來)。
那還有1個位元組的包在抓包裡面沒有顯示,這可能是抓包中把尾包省略了,但是可以從另外一個地方看出來。
在看一個完整的包可以上面的疑惑了
- IP頭部裡面有一個identification 這個是識別符號,分片的包會打上相同的包,方便目的端區分
- 抓包軟體裡面有一個IPV4 Fragments的組合解析,發現有兩個分片,Frame:3,資料負載是0~1479(1480個位元組),Frame:4,資料負載是1480-1481(1個位元組),總共就是1481
- DATA部分為1473,是因為1481裡面有8個位元組的頭部,1481-8=1473個位元組
- 為什麼會影響效率跟增加延遲呢?
可能資料包小,感受不到分片帶來的問題,上圖資料大小改成了5000,會發現4個分片(最後一個是隱藏了),那就會多出4個IP頭部,這些是無故多出來的資料,並且這4個頭部不管是中間裝置還是接收方都需要去解封裝來看是什麼內容,並且接收方根據IP頭部的分片給的資訊去組裝,假設某一個分片中途延遲,那麼這個資料包就不會完整,必須等待這片來組裝後才能讀取到實際的內容,這種會影響效率(多餘的頭部處理),增加延遲(某一個分片沒到,對應的資料沒法重組,導致資料請求遲遲得不到響應。)更嚴重的其實是會加重裝置的負擔(可能實際中不只一個數據包分片,接收方需要把收到的進行快取,等待所有對應的分片來才能讀取到實際的資料,隨著分片越多,快取越大,對於裝置的壓力負擔也越重),如果某一片分配丟失了,會造成這個資料包不完整,被丟棄。
(5)怎麼設定合適的MTU呢
由於現在很多協議還沒學習,不同的應用對應的頭部不一樣,自然包含的內容也不一樣,這個會隨著後面學習的深入,慢慢的瞭解,設定合適的MTU可以用Windows自帶的命令可以探測,比如某個應用有問題,透過抓包發現傳送的資料超過了MTU的大小,就可以適當的調整。
ping命令裡面帶有一個引數-f 它可以把IP包的DF位置1,讓其不分片,那麼超過MTU需要分片的裝置發現DF位置一,則直接丟棄,返回一個ICMP的差錯報文結果,透過這樣來測試出一個合適的MTU值。
留一個小疑問
這裡為什麼1464就可以,1465不可以呢(該環境存在撥號)
“承上啟下”
網路層的基礎知識到這裡就學習完畢了,接下來就進入傳輸層與應用層,對於這兩層,博主會挑對初學者比較重要的部分的講,全部講起來就非常費時間,涉及的內容實在太多,也不是初學者層面能夠理解的,下一篇就進入傳輸層的兩大協議,TCP與UDP。