?? rfc1191.txt
字號:
5. 主機對老式報文的處理
在這一節中,我們概述幾種主機接收來自沒有修改的路由器所發出的數據報太大報文(即,下一跳的MTU字段為0的數據報太大報文)所遵守的策略。這一節不是協議規范的一部分。
主機響應這種報文所作的最簡單的事就是假定PMTU是當前假定的PMTU和576之中的最小值,和停止設置在這條路徑上發送的數據報的DF比特位。這樣,主機會得到和當前實現中選擇的相同的PMTU(見"Requirements for Internet Hosts -- Communication Layers" [1]的3.3.3節)。這種策略的優點就是它終止很快,不差于現存的其他實現。它的缺點就是在一些情況下避免分段失敗,在另一些情況不能最有效利用因特網。
更先進復雜的策略包含對一個精確PMTU估計值的“搜索”,當改變它們的尺寸時,繼續發送帶有DF比特位的數據報。一個好的搜索策略在執行過程中不必產生很多被丟棄的包就可以得到正確的路徑MTU估計值。
一些可能的策略采用前一次估計PMTU的算法函數來產生一個新的估計值。例如,可以用一個常數(比如說,0.75)來乘舊的估計值,得到一個新的估計值。我們不推薦使用這種方法;它要么匯聚的太慢,要么則過多地低估了真正的PMTU。
一個更高級的方法是在包尺寸上作二進制搜索。這種方法匯聚得快了一些,盡管如此,它從FDDI MTU匯聚到以太網MTU仍然需要4至5步。一個嚴重的缺點就是當數據報到另一端的時候(指出當前的估計值太小)為了識別它需要一個復雜的實現。我們也不推薦使用這種方法。
從觀察中發現有一種策略工作的相當好,實際上,相對較少的值使用在因特網中。 因此,與其盲目搜索任意選擇的值,不如只搜索那些可能出現的值。而且,因為設計者傾向于用相似的方法選擇MTU,所以,可能收集到成組的相似的MTU值,使用組中的最小值作為“參考點”。(顯然,低估MTU的百分之幾比高估MTU甚至一個字節也要好)。
在第七節,我們描述了怎樣使用在PMTU估計中有代表性的MTU參考點的表。使用這張表,在最壞情況下匯聚也與二進制搜索一樣好,在普通的情況下則更好(例如,只花費兩次往返的時間就從FDDI MTU到了以太網MTU)。因為參考點位于接近2的次冪的地方,所以如果一個MTU在表中沒有描述,這個算法也不會低估它超過一個2的因數。
為了選擇下一個值,任何搜索策略都必須記住以前的估計值。一種方法就是使用當前緩沖區來保存路徑MTU的估計值,但是,實際上在數據報太大報文本身也包含較好的可用信息。所有ICMP目的不可達報文,包括這一種報文,都包含著原始數據報的IP首部, 此IP首部包含著這個太大的不能分片轉發的數據報的長度。因為總長度可能比當前估計的PMTU小,但是比實際的PMTU大,它對于選擇下一個PMTU估計值的方法來說可能是一個好的輸入。
注意:基于源自4.2BSD Unix實現的路由器對于原始IP數據報的總長度發送一個不正確的值。這些路由器發送的值是原始總長度與原始首部長度的總和(用字節表示)。 因為收到數據報太大報文的主機不可能知道報文是否是由這種路由器中的一個發出的,所以主機必須保守的假定它是的。如果返回的總長字段不小于當前PMTU估計值,它必須減去返回的首部長度字段值的4倍
我們推薦的策略是使用小于返回總長字段的最大的參考值來作為下一個PMTU的估計值(如果必要,根據上面的注意事項進行修改)。
6. 主機實現
在這一節中,我們討論PMTU發現怎樣在主機軟件中實現。這不是一個規范,而是一組建議。
要點包括:
-PMTU發現實現在哪一層或者哪幾層?
-PMTU信息緩存在哪里?
-陳舊的PMTU信息怎樣被刪除?
-傳輸層和更高層必須做什么?
6.1 分層
在IP體系中,選擇發送數據報的尺寸在IP層上層的協議執行。我們把這樣一種協議稱作“打包協議”。打包協議通常是傳輸層協議(例如 TCP),但是也可能是更高層的協議(例如,建立在UDP上層的協議)。
在打包層實現PMTU發現使層內部的一些問題簡化,但是也有一些缺點: 實現可能必須在每一個打包協議中再重做一遍,在不同的打包層之間很難共享PMTU信息,由一些打包層保持的面向連接的狀態不容易擴展來長時間的保存PMTU信息。
因此我們認為IP層應該存儲PMTU信息,ICMP層應該處理收到的數據報太大報文。 通過改變它們發送的數據報的尺寸,打包層必須仍然能夠響應路徑MTU的改變,也必須能確定設置了DF比特位的數據報被發送。我們不想IP層簡單的在每一個包中都設置DF比特位,因為,打包層,也許是核心外部的UDP應用程序可能不能改變它的數據報的尺寸。包含有意分片的協議有時是成功的(NFS是最主要的例子),我們不想打破這種協議。
為了支持分層,打包層需要定義在[1]中的IP服務接口的擴展:
一種得知MMS_S值改變的方法是“最大發送傳輸層報文尺寸”,
它通過路徑MTU減去最小IP首部尺寸得到。
6.2 存儲PMTU信息
通常,IP層應該與它從一條特定的路徑獲得的每一個PMTU值聯系起來。一條路徑是由一個源地址,一個目的地址和一個IP服務類型共同確定的。(一些實現不記錄路徑的源地址;這對于單宿主主機是可接受的,這種主機僅有一個可能的源地址。)
注意:一些路徑可以通過不同的安全分類來進一步區分。
這種分類的詳情超過了本備忘錄的范圍。
存儲這些聯合的明顯的地方是在路由表的條目中作為一個字段。主機不會對每一個可能的目的地都有一個路由,但是對每一個活動的目的地都應該緩存一條主機路由。(必要的條件是需要處理ICMP重定向報文。)
當給主機路由不存在的主機發送第一個數據報的時候,一條路由從一組網絡路由中或者從一組默認路由中選出。 在路由條目中的PMTU字段應該被初始化為關聯的第一跳數據鏈路的MTU,而且在PMTU發現過程中不再被改變(PMTU發現僅僅創建或者改變主機路由條目)。關聯于最初選擇路由的PMTU被假定為正確的,直到接收到數據報太大報文。
當收到一個數據報太大報文時,ICMP層為路徑MTU決定一個新的估計值(要么來自包中的下一跳MTU中的非0值,或者使用第五節描述的方法)。如果這條路徑的主機路由不存在,那么將創建一個(幾乎就象主機ICMP重定向被處理一樣;新的路由使用與當前路由一樣的第一跳路由器)。如果與主機路由關聯的PMTU估計值比新值高,那么此路由條目中的PMTU值將改變。
打包層必須被通知PMTU減小。任意正在使用這條路徑的打包層實例(例如,TCP連接)必須在PMTU估計值減小的時候被通知。
注意:即使數據報太大報文包含一個引用UDP包的源數據報首部,如果有的TCP連接使用這條給定的路徑,TCP層也必須被通知。
同樣,發送引起數據報太大報文的數據報的實例應該被通知它的數據報已經被丟棄了,即使PMTU估計值沒有改變。這是為了它可以重傳丟棄的數據報。
注意:這種通知機制與ICMP源路由抑止提供的通知機制是類似的。在一些實現中(諸如源自4.2BSD的系統),現在存在的通知機制不能識別特別的相關連接,所以,一個附加的機制是必要的。
作為選擇,一種實現能夠避免使用對于PMTU減小的異步通知機制, 這種機制是通過延遲通知直到下一次嘗試發送一個比PMTU估計值大的數據報。在這種方法中,當嘗試發送一個帶有DF比特位設置的數據報,并且這個數據報比PMTU估計值大,SEND函數會失敗,返回一個適當的錯誤指示。這種方法可能更適合于非連接的打包層(例如使用UDP的打包層),它(在一些實現中)可能很難從ICMP層通報。在這種情況下,正常的基于超時的重傳輸機制被使用于從丟失的數據報中恢復。
應該知道打包層實例使用的PMTU改變路徑的通知與包被丟棄的特別通知有區別, 了解這一點很重要。后者是比較實用的(即,從打包層實例的觀點來看是異步的),而前者可能有延遲直到打包層實例想創建一個包。僅當已知包丟失,才應該重傳,這由數據報太大報文指定。
6.3 清除過時的PMTU信息
互聯網網絡拓撲結構是動態變化的;路由隨著時間改變。如果新的路由開始被使用,對指定目的地已發現的PMTU可能是錯誤的。 因此,在主機中緩存的PMTU信息可能變得過時。
因為使用PMTU發現的主機總是設置DF比特位,如果過時的PMTU值太大,一旦一個數據報被發送給指定的目的地,就會立即發現這種情況。認為過時的值太小的機制不存在,所以一個實現應該使緩沖值“變老”。當一個PMTU值一段時間內沒有減少(在預訂的10分鐘內),PMTU估計值應該被設置為第一跳數據鏈路MTU,打包層應該被通知這種改變。 這將導致完全的PMTU發現過程再次發生。
注意:實現應該提供改變超時持續時間的方法,包括設置它為“無限”。 例如,連接在FDDI網絡上的主機通過一條低速的串行線接入因特網將不會發現一個新的非本地的PMTU,所以它們不必忍受每十分鐘丟棄數據報。
在響應PMTU估計值增長的時候,上層不必重傳數據報。因為在響應丟棄數據報的指示的時候,增長從不發生。
一種實現PMTU老化的方法是在路由表條目中加入時間戳字段。這個字段初始化為一個“保留”值,表明PMTU從沒改變過。當響應一個數據報太大報文,PMTU減少的時候,時間戳被設置為當前時間。
通過時間驅動的過程將立即處理路由表,對于時間戳不是“保留”并且比超時時間間隔老的條目:
- PMTU估計值被設置為第一跳的MTU。
- 使用路由的打包層被通知這種增長。
如果主機路由被刪除,PMTU估計值可能從路由表中消失; 這可能發生在響應一個ICMP重定向報文的情況中,或者因為某些路由表守護程序在幾分鐘后刪除了舊的路由。在一個多宿主主機上拓撲改變也可能導致使用不同的源接口。當這種情況發生,如果打包層沒有被通知,那么它可能繼續使用對現在來說太小的緩沖PMTU值。一種解決方法就是當重定向報文導致路由改變和路由從路由表中刪除時通知打包層PMTU可能改變。
注意:檢測PMTU增長的更高級復雜的方法在7.1節中描述。
6.4 TCP層的行為
TCP層必須追蹤連接到目的地的PMTU;不應該發送比它還大的數據報。一個簡單的實現可能在每次創建一個新的段的時候,向IP層請求這個值(使用在[1]中描述的GET_MAXSIZES接口),但是這種方法效率不高。而且遵守“慢啟動” 避免阻塞算法[4]的TCP實現計算和緩存從PMTU得到的一些其它的值。當PMTU改變的時候接收異步的通知較為簡單,以至于這些變量可以更新。
TCP實現也必須存儲從它的對等者那里接收的MSS值(默認為536),不發送任何比MSS大的段,而不管PMTU的值是多少。在源自4.xBSD的實現中,這需要加入一個附加的字段給TCP狀態記錄。
最后,當收到數據報太大報文的時候,這意味著一個數據報被發送這個ICMP報文的路由器丟棄。把它作為任意其它種類被丟棄的段,等待重傳計時器期滿導致這個段重傳,這樣的行為就足夠了。如果PMTU發現過程需要一些步驟來估計正確的PMTU,這可能因為要往返許多次數據報而造成連接延遲。
作為選擇,重傳可以在對路徑MTU已改變的通知立即響應時發生,但是這僅僅對于由數據報太大報文指定的特定連接。使用在重傳中的數據報尺寸當然應該沒有新的PMTU大。
注意:在響應每一個數據報太大報文的時候一定不要重傳相同大小的段,因為特大型的段的突發將造成這樣的報文,所以會重傳同樣的數據。如果新估計的PMTU值仍然錯誤,這個過程重復,送的多余段的數量將成幾何級增長。
這意味著當數據報太大通知實際上減少已經使用在給定的連接中發送數據報的PMTU時,TCP層必須能夠識別,并且忽略任何其它的通知。
現代的TCP實現把“避免阻塞”和“慢啟動”算法結合起來提高性能[4]。不象由TCP重傳超時導致的重傳,由數據報太大報文導致的重傳不應該改變擁塞窗口。然而,它應該觸發慢啟動機制(即,只有一個段將被重傳直到確認開始到達)。
如果發送者最大窗口的尺寸不是使用中段尺寸的準確的倍數(這不是擁塞窗口尺寸,它 總是段尺寸的倍數),TCP性能可能降低。在許多系統中(諸如從4.2BSD中發展的系統), 段尺寸總是設置為1024字節,最大窗口尺寸(“發送空間”)總是1024字節的倍數, 所以,這種適當的關系保持為默認。然而,如果PMTU發現被使用,段尺寸可能不是發送空間的約數,而且它可能在連接中改變;這意味著當PMTU發現改變PMTU值時,TCP層可能需要改變傳輸窗口尺寸。最大窗口尺寸應該被設置為小于或等于發送者緩沖區空間尺寸的段尺寸(PMTU - 40)的最大倍數。
PMTU發現不影響在TCP MSS選項中發送的值,因為這個值用在連接的另一端,它可能使用一個不相關的PMTU值。
6.5 其它傳輸協議的問題
一些傳輸層協議(例如ISO TP4 [3])在重傳的時候,不允許重新打包。也就是說,一旦試圖傳輸某種尺寸的數據報,它的內容就不能分成較小的數據報重傳。在這種情況下,原始數據報應該不設置DF比特位重傳,允許它作必要的分段來到達它的目的地。當第一次傳輸的時候,后來的數據報應該沒有路徑MTU允許值大,并且應該設置DF比特位。
在許多情況下,Sun 網絡文件系統(NFS)使用遠程過程調用(RPC)協議[11]發送必須分段的數據報,甚至對第一跳鏈路也是如此。在某些情況下,這可能提高性能,但是眾所周知它也導致可靠性和性能的問題,尤其是當客戶端和服務器被路由器分開的時候。
當涉及到路由器的時候,我們建議NFS實現使用PMTU發現。大多數NFS實現允許在安裝的時候改變RPC數據報尺寸(間接的,通過改變有效文件系統塊尺寸),但是可能需要一些修改來支持以后的改變。
而且,因為一個單一的NFS操作不能分開成一些UDP數據報,某些操作(主要是在文件名和目錄上的操作)需要可能比PMTU大的最小數據報的尺寸。NFS實現不應該減少數據報的尺寸小于這個極限值,即使PMTU發現建議了一個較小的值。(當然,在這種情況下數據報發送時不應該再設置DF比特位。)
6.6 管理接口
我們建議實現提供一種適合于系統公用程序的方法:
- 確定在給定的路由上沒有使用PMTU發現。
- 改變與給定路由相關的PMTU值。
前者通過與路由條目關聯一個標志來完成。當一個發送的包經過具有這個標志的路由的時候,IP層把DF比特位清除,而不管上層的請求如何。
這些特性可以使用在不規則的情況中,或者用在能夠得到路徑MTU值的路由協議實現中。
實現應該提供一種方法改變使PMTU信息變老的超時周期。
7. 路徑MTU的可能值
在第五節建議的“搜索”路徑MTU空間的算法基于嚴格限制搜索空間的取值表。我們在這里描述的MTU取值表聲明了在因特網中使用的所有主要的數據鏈路技術。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -