金秋十月,在這國慶和中秋雙節之際,首先祝福你們雙節快樂。程序員
今天讓咱們來聊聊MTU的話題。網絡
相信不管網工仍是程序員,都會多多少少的碰到過由MTU引起的問題,也每每對MTU值的選擇和計算頭疼不已。ide
一般狀況下,咱們能夠經過調整TCP-MSS值的大小,或者使用Path-MTUDiscovery 等技術來解決處理。工具
可在某些環境較爲複雜的狀況下,這些工具可能就不那麼好使了。性能
因此若是不完全瞭解MTU的定義以及相關工具的工做原理。出現問題後排錯就顯得尤其困難了。測試
爲了完全搞懂MTU,我將用兩篇文章給你們介紹什麼是MTU以及相關工具的工做原理。spa
1. 第一篇文章主要內容爲MTU的定義以及數據包分片技術細節。計算機網絡
2. 第二篇文章將要介紹如何自動發現最佳MTU值以及相關工具,以及在特定場景下MTU所產生的問題以及解決方法,例如IPSec***,或者不一樣網絡環境OSPF,BGP對接等。3d
既然要討論MTU工做原理,那首先須要明確MTU的定義。orm
相信你們都見過平常道路上的限高杆,其做用是限制道路上的車輛高度。在計算機網絡環境裏面,MTU就是鏈路上的限高杆,與現實世界的道路類似,在網絡世界裏面不一樣介質的鏈路也存在不一樣的MTU值。
嚴格來講,雖然說單個IP數據包最大長度可達65535字節。而在傳輸過程當中,傳輸鏈路規定了單個數據包傳輸長度。當IP數據包長度超過此長度後,數據包將被切割爲小於或等於鏈路規定長度的小IP包。
此規定長度就是MTU值,全名爲:Maximum Transmission Unit 最大傳輸單元。
讓咱們來看看通常狀況下,各個介質下的MTU值。(單位:字節)
上圖能夠看出,不一樣鏈路存在不一樣的MTU值,以常見的以太網MTU值爲例,其MTU值通常爲1500字節。那這1500字節都包含了些什麼?
以下,以Juniper的 SRX接口輸出內容爲例:
lab@SRX01> show interfaces ge-0/0/2
Physical interface: ge-0/0/2, Enabled, Physical link is Up
Interface index:136, SNMP ifIndex: 519
Link-level type:Ethernet, MTU:1514, Link-mode: Full-duplex, Speed: 1000mbps
<此處省略多餘輸出>
Logical interfacege-0/0/2.0 (Index 72) (SNMP ifIndex 528)
<此處省略多餘輸出>
Protocol inet, MTU:1500
Flags:Sendbcast-pkt-to-re
Addresses,Flags: Is-Preferred Is-Primary
Destination:1.1.1/24, Local: 1.1.1.1, Broadcast: 1.1.1.255
<此處省略多餘輸出>
你們能夠看到,上面提到了兩個MTU值,分別是1514 和1500。
先說說1514,從「Link-level type:Ethernet」能夠看出,它是ISO模型第二層鏈路層的MTU值。1514字節包含了以下內容:
<二層以太網幀頭14字節> --<數據包負載1500字節:包含三層IP頭,四層或以上內容>
而1500爲ISO模型第三層網絡層的MTU,從「Protocol inet」能夠看出,1500字節包含了全部網絡層的數據,從IP包頭到傳輸層UDP/TCP包頭,甚至應用層的用戶數據。
<3層IP頭20字節>--<數據包負載1480字節:包含四層或者以上內容>
小結,MTU值取決於兩個因素:
1. 不一樣鏈路介質存在不一樣MTU值
2. 相同鏈路下,不一樣ISO層級也存在不一樣MTU值,原則上低層級的MTU值是大於高層級的MTU值,爲包含關係。
在理解MTU的定義之後,能夠看出其實MTU就是一個普普統統的鏈路數據包大小閾值,就其自己而言,它沒有任何定義上的錯誤,那爲何江湖上還有這麼多關於MTU引發的紛爭呢?
緣由在於互聯網世界中,不可能單存使用某一種介質的鏈路。
而就算在普遍使用的Ethernet以太網中,也存在了使用不一樣技術從而致使MTU值不相同的例子,例如你們熟知的GRE隧道,IPsec隧道,PPPOE接口等虛擬邏輯接口等。
當數據包穿越不一樣MTU值的鏈路時,每每就會出現各類問題。就比如高速路換普通公路必然會引發擁堵同樣。MTU不匹配也會致使諸多問題。
如下爲常見的MTU不匹配致使的網絡問題:
1. 由於鏈路MTU不匹配問題致使網絡產生大量分片數據包,從而影響路由器包轉發效能。
2. 在IPsec ***環境下,一樣由於分片包緣由,致使***吞吐量降低50%以上。
3. 二層鏈路MTU值低於三層鏈路MTU值從而致使數據包被丟棄。
4. 某些路由協議由於MTU值不匹配緣由致使協議創建不成功。
總的來講,絕大部分仍是和數據包分片有關,所以這裏有必要花點篇幅來討論下數據包分片的細節。也爲後續章節作準備。
爲了便於理解,先來看一個由於MTU值緣由致使數據包傳輸過程當中被分片的案例:
lab@SRX01>ping 2.2.2.2 size 1500 source 1.1.1.1 count 2
一臺名爲SRX01的路由器ping了另一臺路由器SRX02 兩次,每一個ping數據包長度爲1500字節。
中間鏈路抓包後,截圖以下:
如上圖所示,IP爲1.1.1.1的主機ping了IP爲2.2.2.2的主機兩次。但因爲數據包自己長度1500字節,額外還要加上IP和ICMP包頭的長度,很明顯總長度超過了網絡層的MTU值1500字節,致使數據包被分片。
繼續深刻分析:
你們請注意,在數據包長度部分(Length),第一個數據包總長爲1514字節,第二個數據包總長爲62字節。那這長度是怎麼計算的?
在開始計算以前,再次強調ping 數據包長度爲1500字節,不包含IP頭長度以及ICMP頭長度。
先看看第一個數據包的1514怎麼計算:
首先1514字節包含了二層鏈路幀頭,三層IP包頭,以及ICMP包頭,最後是ping 的數據等。
用一個等式能夠輕鬆理解1514的計算方法:
1514字節=14字節以太網二層幀 + 20字節三層IP包頭 +8字節ICMP包頭+1472字節數據包。
那接下來剩下的62字節分片數據包怎麼計算?答案以下:
62字節= 14字節以太網二層幀 + 20字節三層IP包頭 + 剩餘28字節數據包
(注:28字節=總長1500字節數據包– 已經傳輸的1472字節數據包)
乍看之下,IP數據包分片不就是數據包大於MTU就被切割傳輸了?
可是仔細想一想,不少問題尚未解釋清楚?
例如:
1. 誰決定了究竟是否分片,中間鏈路的路由器仍是收發端?
2. 數據包接收方怎麼知道這是否是分片包?
3. 由於時延的問題致使數據包到達順序不一致,接收方怎麼正確重組數據包?
4. 當有成千上萬個不一樣流量的分片數據包同時到達接收方,由於分片數據包只存在IP包頭+剩餘數據,而缺乏傳輸層包頭,那接收方怎麼甄別數據包屬於某個上層協議?
爲了回答以上問題,咱們須要詳細理解IP分片包的工做機制。
仍是以Ping測試爲例,本案中主機A向主機B Ping 4000字節數據包。網絡中間鏈路MTU爲標準的1500字節。
藉助一個形象化的比喻:咱們能夠把一個數據包比喻爲一輛貨車,以下圖。主機A點發出了一個×××大卡車,攜帶貨物爲4000字節長度,大卡準備駛向主機B點。同時爲了讓主機B點知曉貨物內容以及收貨人具體信息等,在這4000字節長度的貨物上又封裝了一個裝箱單。
數據包生產過程:
主機A在產生數據包的時候會一次性把全部數據塞進一個完整的數據包(×××大卡車),此數據包包含了二層幀頭,三層IP頭(×××大卡車頭),ICMP頭(裝箱單),同時也包含了有效載荷4000字節(貨物)。
數據包傳輸過程:
當數據包經過途中某個鏈路時,三層網絡層鏈路MTU(道路限高)爲1500字節。由於包大小4000字節大於1500字節,這個時候數據包面臨兩個選擇:分仍是不分!
不分片,數據包就被無情被丟棄。
而分片就須要卸下負載(貨物),換成小數據包在傳輸(大卡車換小麪包車)。
那你說到底誰決定是否容許分片?
答案:決定數據包是否須要分片取決於始發地的主機A,主機A會往IP數據包裏面寫入一個叫作DF(don't-fragment)的字段告訴其餘路由器是否容許對此數據包進行分片操做。
若是值設置爲1,表示主機A不想讓數據包被其餘路由器分片。反之如何值爲0,則容許分片。
例以下圖,此數據包就被始發地A標記:請不要分片!
可是如設置了不想分片,那遇到鏈路MTU值比數據包小的狀況下,數據包就會被中途的路由器丟棄。
在這裏,咱們假設始發地A容許分片。(DF=0)
分片本質上就是把數據包的負載(大卡車上的貨物+裝箱單)卸下後,根據鏈路限高來分割負載(貨物+裝箱單)並換成更小的數據包(麪包車)來運輸。但隨之而來的問題是:分割後的每個數據包都須要一個新包IP包頭來運輸數據包(每一輛麪包車的車頭),因此在計算總體數據包大小是否知足鏈路MTU值的時候,新IP包頭大小也得計算在內,畢竟過限高杆的時候車頭大小也是須要考慮的。
在本例中,以網絡層1500字節MTU爲標準,這4000字節加上包頭的數據包被分爲了三個小數據包,大小以下:
第一個包:1514字節(包含14字節二層幀)
包內容:14字節以太網幀頭+20字節IP頭+8字節ICMP頭+1472字節負載
第二個包:1514字節(包含14字節二層幀)
包內容:14字節以太網幀頭+20字節IP頭+1480字節
第三個包:1082字節(包含14字節二層幀)
包內容:14字節以太網幀頭+20字節IP頭+1048字節
你們有沒有發現,只有第一個包存在ICMP包頭,後續的數據包再也不封裝ICMP包頭。其實很簡單,借用咱們的比喻,這ICMP包頭就是裝箱單,在貨物被切割的是,裝箱單就跟着第一個數據包走了,咱們總不至於把裝箱單撕成碎片分別放到不一樣的小麪包車上吧。
另一個問題,由於分片是在途中發生,接收方的主機B徹底不知情。原本主機B但願進門的是一個×××大卡,結果來了幾輛小麪包車,若是不說明清楚主機B確定不接收貨物。那麼咱們頗有必要須要讓其知道,中間大卡由於超載被強制換成小麪包車了。
答案:當路由器在分片數據包的時候,會在IP包頭處放置另一個標記:more fragment(更多分片)。
除了分片最末尾的數據包外,其餘全部分片數據包都存在此標記。
而末尾數據包之因此不存在此標記,則是由於它是最後一個,後續再也沒有分片數據包了。
同時,在分片過程當中,除了標記「更多分片」讓主機B瞭解數據包被分片以外,咱們還須要告知主機B數據包的分片順序。從而引出以下問題:
答案:當數據包被分片時,路由器會根據其IP包載荷計算每個包的起始位置,稱做分片偏移量。接收端主機B會根據其偏移量來重組數據包。假如由於網絡延遲緣由,分片最後一個包先於其餘兩個數據包到達。經過偏移量,主機B會等待全部數據包到達之後,重組數據包。
本例中,第一個包的起始位置爲0,因此其offset偏移量爲0。而第二個包起始位置爲第一個包的末端。本例爲1480字節。以此類推,第三個數據包起始位置爲第二個數據包的末端,爲2960字節。(第一個1480+第二個1480=2960字節)
數據包對好比下:
以上爲第二個數據包的1480字節偏移量示例。
上圖爲三個分片數據包offset偏移量彙總,其結果與咱們所分析的徹底一致。
答案:有了上面介紹的offset偏移量之後,當主機B接收到分片數據包,它會在根據另一個參數最終確認全部的分片是否源自同一個源數據包,並完成重組。此參數爲:Identification(數據包ID)。
以下圖:
顧名思義,數據包ID相似於你們的×××同樣,用來惟一標識某一個數據包。當數據包被分片後,同屬於某一個源數據包的全部分片包將會使用同一個ID號。當數據包到達目的地主機B之後,主機B能夠經過識別ID的方式在成千上萬個不一樣數據包流中識別出相同源的數據包流,完成數據包重組。
在咱們的示例中,當一個個的小麪包車最後所有到達主機B之後。B站根據上面的信息把全部負載重組,並根據第一個小麪包車的裝箱單(第一個數據包的icmp 包頭)把負載遞交給上層協議ICMP,從而完成整個傳輸過程。
本篇咱們一塊兒分析了MTU的定義,以及數據包在網絡鏈路中出現的分片緣由以及計算方法等。
總的來講,因爲MTU不匹配的緣由,數據包會出現以下兩種狀況,
1. 數據包不能被分片,從而被丟棄。
由於數據包被丟棄,某些協議沒法工做正常。同時也會影響例如對丟包很是敏感的TCP協議性能。
2. 數據包被分片並傳輸到目的地。
雖然數據包最終被完整的傳輸到目的地。但在分片過程當中,路由器不得不花費更多的硬件資源來處理並轉發數據包。一方面引入了數據包的延遲,同時也增長了路由器的數據包轉發量。
借用卡車的例子,在卡車卸貨並裝車過程當中,你們很容易想到這會須要花費更多的人工處理時間,同時把原來一輛車能處理的負載變爲多輛車同時處理,無形中增長了後續傳輸道路的汽車擁堵程度。
上篇就此結束,下篇中我將要帶領你們一塊兒分析什麼是TCP-MSS,Path-MTU Discovery。經過自動發現MTU值,從而儘量避免數據包分片的發生。同時簡要分析三種MTU致使的常見問題,敬請期待。