MTU是Maximum Transmission Unit的縮寫,意爲最大傳輸單元,通俗的理解就是在網絡上傳送的最大數據包,單位是字節。服務器
以太網對數據幀的長度都有一個限制,其最大值爲1500,這個特性被稱做MTU,不一樣類型的網絡大多數都有一個上限。若是IP層有一個IP包要傳,並且數據的長度比鏈路層上的MTU值還要大,那麼就須要對這個數據包進行分片處理,並且要求被分片的每一個數據包都要等於或小於這個MTU值,通常是最後一個數據包小於這個值。例如,一個大小爲5000字節的數據包在穿越網絡時,若是遇到一條MTU大小爲1500字節的數據鏈路,即數據幀對多能容納大小爲1500字節的數據包。須要在數據成幀以前將數據包分片成多個小的數據包。被分片後,每片數據包的標示字段上打上相同的標記,以便接收者能夠識別出屬於同一個數據包的分片。若是不分片,該數據包就會被丟棄,從而形成數據包丟失。可是,若是由於MTU值設定得過小,以至於一個不是很大的數據包被分紅許多片進行傳輸,這樣就會產生不少數據包碎片,增長了設備負擔,下降了網絡使用率。網絡
EthernetII幀的結構DMAC+SMAC+Type+Data+CRC。因爲以太網傳輸電氣方面的限制,每一個以太網幀都有最小的大小64bytes,最大不能超過1518bytes,對於小於或者大於這個限制的以太網幀咱們均可以視之爲錯誤的數據幀,通常的以太網轉發設備會丟棄這些數據幀。 小於64Bytes的數據幀通常是因爲以太網衝突產生的「碎片」或者線路干擾或者壞的以太網接口產生的,對於這些小於64Bytes的「碎片」,MAC子層就會在數據字段的後面填充以知足整個數據幀長不小於64字節,以便傳輸。tcp
爲何以太網規定會規定數據幀長度不小於64字節?測試
以太網是不可靠的,這就意味着發送者並不知道本身發出的數據對端是否收到,但若是它發出的數據包出現錯誤,則會進行重傳。何時會發生錯誤,發生錯誤是指什麼呢,以太網是如何檢測到錯誤的?大數據
以太網的錯誤主要是發生碰撞,碰撞是指兩臺機器同時監聽到網絡是空閒的,同時發送數據,就會發生碰撞,碰撞對於以太網來講是正常的。很是有名的CSMA/CD就是用來檢測衝突的。假設A檢測到網絡是空閒的,開始發數據包,盡力傳輸,當數據包尚未到達B時,B也監測到網絡是空閒的,開始發數據包,這時就會發生碰撞,B發現發生碰撞,開始發送碰撞信號,所謂碰撞信號,就是連續的01010101或者10101010,十六進制就是55或AA。這個碰撞信號會返回到A,若是碰撞信號到達A時,A尚未發完這個數據包,A就知道這個數據包發生了錯誤,就會重傳這個數據包。但若是碰撞信號會返回到A時,數據包已經發完(在數據包比較短的狀況下),則A不會重傳這個數據包。網站
以太網爲何要設計這樣的重傳機制。首先,以太網不想採用鏈接機制,由於會下降效率,但他又想有必定的重傳機制,由於以太網的重傳是微秒級,而傳輸層的重傳,如TCP的重傳達到毫秒級,應用層的重傳更達到秒級,咱們能夠看到越底層的重傳,速度越快,因此對於以太網錯誤,以太網必須有重傳機制。要保證以太網的重傳,必須保證A收到碰撞信號的時候,數據包沒有傳完,要實現這一要求,A和B之間的距離很關鍵,也就是說信號在A和B之間傳輸的來回時間必須控制在必定範圍以內。IEEE定義了這個標準,一個碰撞域內,最遠的兩臺機器之間的round-trip time 要小於512bit time.(來回時間小於512位時,所謂位時就是傳輸一個比特須要的時間)。這也是咱們常說的一個碰撞域的直徑。512個位時,也就是64字節的傳輸時間,若是以太網數據包大於或等於64個字節,就能保證碰撞信號到達A的時候,數據包尚未傳完。spa
512bit time是如何得來的?設計
先看一下一個比較古老但流行一時的標準:10BASE5,一種以太網標準,該標準用於使用粗同軸電纜、速度爲10Mbps的基帶局域網絡,在總線型網絡中,最遠傳輸距離爲500米。網絡節點裝有收發器,該收發器插在網卡上的15針鏈接單元接口(Attachment Unit Interface)中,並接到電纜上。也做thick Ethernet,ThickNet,ThickWare。另見coaxial cable,Ethernet,指的是使用標準的(粗)50Ω基帶同軸電纜的10Mbit/s的基帶以太網規範。它是IEEE802.3基帶物理層規範的一部分,在每一個網段上的距離限制是500m,整個網絡最大跨度爲2500m,每一個網段最多終端數量爲100臺,每一個工做站距離爲2.5m的整數倍。上面提到的這個碰撞域的來回時間其實就是當時依據10M網絡的標準來定義的,10BASE5容許最遠的兩個工做站間距離2.5千米 ,電子信號在2.5千米來回時間約爲51.2us。根據CSMA/CD,最小封包以51.2us計算和10Mbps計算:51.2us * 10Mbps = 512 bit = 64 byte。這就是爲何以太網要最小64個字節的歷史緣由了,一個是基於CSMA/CD的須要,另一個就是依據了當時10M網絡的標準進行了計算和定義。3d
以太網幀最大不能超過1518bytes,這也是一個規定,但沒有上述的這些限制,之因此規定爲1518,主要是考慮到傳輸效率正確率。因爲以太網EthernetII最大的數據幀是1518Bytes,這樣,除去以太網幀的幀頭(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和幀尾CRC(FCS)校驗部分4Bytes。那麼剩下承載上層協議的地方也就是Data域最大就只能有1500Bytes這個值咱們就把它稱之爲MTU。這個就是網絡層協議很是關心的地方,由於網絡層協議好比IP協議會根據這個值來決定是否把上層傳下來的數據進行分片。就比如一個盒子無法裝下一大塊麪包,咱們須要把麪包切成片,裝在多個盒子裏面同樣的道理。blog
爲何在PPPOE撥號鏈接的狀況下,將MTU設置大於1492時會出現ping大包不通的狀況呢?先要弄清楚,MTU包含了那些東西,值是怎樣算出來的?在上述網絡環境下,路由器撥號接口下的MTU值設置爲1500,主機ping www.qq.com –l 1470測試時抓包查看。此時是不能ping的。命令ping www.qq.com –l 1470中的1470表示的是這個ICMP包的淨載荷數據長度爲1470字節。結合上圖,抓取的ICMP報文中包含:Ethernet Header、IP Header、ICMP - Internet Control Messages Protocol及FCS - Frame Check Sequence等內容。其各項所佔字節長度以下表:
項目 |
內容 |
長度(字節) |
備註 |
Packet Length |
|
1516 |
數據包總長度 |
Ethernet Header
|
Destination |
6 |
目的MAC及源MAC分別爲48Bit,分別佔6字節 |
Source: |
6 |
||
Protocol Type: |
2 |
||
IP Header |
Header Length: |
20 |
IP報頭 |
ICMP |
ICMP Type |
8 |
ICMP報頭 |
ICMP Data Area: |
1470 |
ICMP淨載荷長度 |
|
FCS |
|
4 |
幀校驗序列號 |
在這個ping包截圖中,MTU值計算時包含了IP報頭、ICMP報頭及ICMP淨荷載長度即20+8+1470=1498。按一般理解1498明顯小於撥號接口下的MTU值1500,這時候不須要分片,該ICMP包應該是被正常發送出去的。但爲何不能ping通呢?那是在以太網鏈路上的狀況。那麼在經過PPPOE撥號上網時,MTU又包含哪些東西呢?所謂PPPoE就是在以太網上面跑PPP協議, PPP協議和Ethernet不都是鏈路層協議嗎?怎麼一個鏈路層跑到另一個鏈路層上面去了,難道升級成網絡層協議了不成。其實這是個誤區:就是某層協議只能承載更上一層協議。PPPOE協議棧以下:
IP |
PPP |
PPPoE |
Ethernet |
爲何會產生這種奇怪的需求呢?這是由於隨着寬帶接入(這種寬帶接入通常爲Cable Modem或者xDSL或者以太網的接入)因爲以太網缺少認證計費機制而傳統運營商是經過PPP協議來對撥號等接入服務進行認證計費的,因此就出現了PPPoE。
再看PPPOE的數據報文格式:
版本 |
類型 |
代碼 |
會話ID |
長度 |
淨載荷 |
pppoe是經過以太網傳輸的,其含有PPPOE協議頭有6個字節和以太網幀類型2字節。這個8字節的PPPOE封裝字段會在數據從撥號接口發送出去時被添加到數據報文中。所以,該數據報文從撥號接口出去時的真實長度是1498+8=1506大於物理以太網接口F0/1的MTU值1500,所以,該數據包將會被丟棄,從而出如今主機上用ping www.qq.com –l 1470不通的狀況。PPPoE帶來了好處,也帶來了一些壞處,好比:二次封裝耗費資源,下降了傳輸效能等等,最大的壞處就是PPPoE致使MTU變小了,以太網的MTU是1500,再減去PPP的包頭包尾的開銷(8Bytes),就變成1492。經過上面的分析,在PPPOE環境下,設置接口MTU時須要將8個字節的PPPOE封裝字段考慮進去,MTU=1500-8=1492,這樣,當IP報頭(20)+ICMP報頭(8)+ICMP淨荷載長度+PPPOE頭(8)<=物理接口1500(即ICMP淨載荷<=1500-28=1472)時,該數據包不會由於數據包長度超過接口MTU值被丟棄,並且還能夠在不須要分片的狀況下最大限度的發送數據包,提升傳輸效率。
當以個數據包的長度比鏈路層上的MTU值還要大,那麼IP層就須要對這個數據包進行分片處理,並且要求被分片的每一個數據包都要小於這個MTU值。下面仍然經過實驗抓包的方式來分析數據包是如何分片的。在PC上執行ping www.qq.com –l 1600,1600爲ICMP淨載荷數據長度。
跟數據包分片有關的幾個字段:
Identifier(標示符):該字段長度爲16,一般與標記字段和偏移字段一塊兒用於數據包分片。
Fragmentation Flags(分片標記):長度爲3,其中第1位沒有使用,第2位是不分片(DF),當DF位被設置爲1時,表示路由器不能對數據包進行分片處理(對於一些上層TCP應用程序,由於某些緣由,要求不能對該應用的數據包進行分片,這時候就須要將DF爲設置爲1)。若是數據包由於不能分片而未能被轉發,路由器則會丟棄該數據包,並向源點發送錯誤消息,這一功能能夠用工做在網絡上測試MTU值。
第3位表示還有更多的分片(MF)位,當路由器對數據包進行分片時,除了最後一個分片的MF位設置爲0外,其餘全部分段的MF位都設置爲1,以便接受者直到收到MF位爲0的分段爲止。
數據包被分片後每一個分片的大小是否同樣,分片大小是隨機仍是有規律可循?數據包在被分片時,是依照最大淨載荷字節長度盡力讓每一個分片包大小都達到MTU容許的上限值,這樣能夠提升數據傳輸的速率。好比,主機A向主機B發送了4個大小爲3000的數據包,每個數據包都被分片爲3個分片包,第一個分片包大小與第2、三個分片包的大小是怎樣的呢?根據PPPOE下最大MTU爲1492的規定以及分片標記的工做原理,每一個數據數據包的最大淨載荷爲1472字節,因此該大小爲3000字節的大包會被分片爲淨載荷分別爲1472字節、1472字節及48字節的數據包。所以主機A發往B的4個3000字節的大包被分片的狀況是徹底同樣的。
Fragment Offset:(分段偏移):字段長度爲13位,以8個8位組爲單位,用於指明分段起始點相對於報頭起始點的偏移量。因爲分段到達時可能錯序,因此分片偏移字段可使將接收者按照正確的順序重組數據包。
綜上所述,當主機向目的服務器地址222.73.78.203發送一個長度爲1600字節的ping包時,這個ping包被髮送到主機網卡(主機網卡MTU值默認爲1500),網卡將這個數據包分片成2個包,第一個包總長度爲1500(1472+20+8)字節,第二個包總長度爲148(128+20)字節。第一個分片包經由交換機轉發(交換機接口MTU爲1500,且不進行分片處理)給路由器,路由器的內網口F0/0也不作分片處理,這個長度爲1500的分片包被轉發路由器的虛擬接口時,再次被進行分片處理(由於該虛擬接口的MTU值爲1492),被分片的數據包在出虛擬接口時被加上8個字節的PPPOE頭,因爲被分片後的數據包長度小於外網口F0/1的MTU值1500,所以從物理口F0/1轉發出去。被分片的數據包不會在數據鏈路的另外一端被重組,而是一直保持分片狀態,直到到達最終目的地時纔會根據分片標記字段中的標記被重組。
TCP-MSS是Maximum Segment Size 最大分段大小的縮寫,意爲TCP數據包每次可以傳輸的最大數據分段,是TCP協議裏面的一個概念 ,default value is 536。
MSS值所表示的是TCP報文的淨載荷數據大小。經過設置其大小能夠達到與設置MTU值同樣的效果,都是爲了不主機發送的數據包大小超過網絡鏈路MTU值而形成數據包被丟棄的狀況。可是在實際狀況中,該MSS值在TCP協議中實現的時候每每被MTU所代替。其實現原理是:一些TCP實現只有當目的主機在一個非直接鏈接網絡上才發送MSS選項,pc上網或者別的一些tcp鏈接,PC會與目的地的IP地址,協商一次mss參數,做爲本身發送數據包的參考。mss參數就是告訴對端本端最大支持不分片的數據包大小,只含淨荷。
MSS是TCP數據包每次可以傳輸的最大淨載荷數據分段。TCP MSS 被定義爲相關的IP數據報尺寸減去TCP報頭(20)和IP報頭(20)即爲40,而最大IP數據報尺寸的默認值是576,這就致使TCP MSS的默認值是536字節。在以太網鏈路上容許傳輸的最大IP數據包長度即MTU爲1500,這也就致使MSS的最大值爲1500-20-20=1640,而在PPPOE撥號的環境下,還須要減去8個字節的PPPOE封裝頭,所以PPPOE下的撥號接口的MSS最大值爲1500-20-20-8=1452。
TCP報文中MSS的位置就在選項的位置,選項中內容有不少種,MSS是其中的一種。MSS在TCP報文中是可選項不是必選項,換句話說MSS是可協商的,並且在協商事後該選項內容能夠改變也能夠沒有,在協商MSS時通常是創建TCP鏈接的兩端發送[Syn]標誌報文時互相通報而後選取最小MSS做爲雙方的約定,若是雙方都不通報或有一方不通報通常選擇MSS的默認值536。在這裏不由要問,TCP不是屬於應用層的嗎,MSS是TCP的屬性選項,爲何會由IP來處理呢?這是由於一般TCP層不可能有適當地信息來做出這種決定,全部它更願意把決定因特網路徑合適的MTU的工做留給IP層來完成。
在PC訪問網站服務器時,會在TCP鏈接階段協商MSS值和其餘的一些參數。而後PC使用默認的1460字節MSS向網站服務器發送TCP鏈接請求。所以,在使用PPPOE方式上網時,PC與網站服務器之間經過協商好的1460字節發送數據包,這個數據包通過封裝加上TCP頭和IP頭後,到達路由器虛擬接口時,路由器會檢查其接口的MTU值,發現這個數據包大於其設定好的MTU值1492,就會將該數據包分片成2個數據包進行發送。但網站認爲,咱們之間已經協商好了MSS值,就只接受MSS定義好長度的報文,任何大於或小於該MSS長度的報文都是無效,我會將它丟棄,這就會形成有些應用或某些網站沒法打開的狀況。當在路由器上設置了ip nat mss 1452命令後,當PC按照1460字節的MSS向網站發送TCP鏈接請求時,路由器接收到該請求,發現1460的設置加上報文頭後會超過了最大的1492的限制,就會將該MSS值減8,即爲1452,而後將修改後的鏈接請求發送給須要轉發的網站。這樣該網站若是贊成路由器轉發的該鏈接請求,TCP鏈接就能夠創建成功。這樣之後PC訪問該網站時,最大就只會發送1492字節的IP報文。
在文章的概述部分,已經對什麼是TCP-MSS,其做用是什麼作了描述,如今仍然用實驗抓包的方式來對其分析。
在PC訪問www.qq.com網站時,PC與服務器之間會創建TCP協商,PC與服務器之間會相互通報本身本端的MSS值,而後選取最小的MSS值做爲雙方的約定。這一點經過深刻的分析一下TCP協商時的數據報文就能得出結論,咱們對比如下PC1訪問網站的第一個數據報文和網站返回的第一個數據報文的具體狀況。