iSCSI錯誤恢複基於以下的攷慮:
1
PDU在網絡傳輸過程中可能出現數據錯誤。TCP/IP爲UDP的傳輸提供了可靠保證,但iSCSI認爲那並不充分,出錯的PDU有可能逃過TCP/IP
的16位較驗和的檢測而被當做正確的數據返回到iSCSI層,iSCSI發現錯誤並丟棄該PDU。iSCSI有必要實現對這些被丟棄的PDU的恢複功能。
2 TCP/IP連接在進行數據傳輸時隨時都可能失效。iSCSI有一定條件下,應該允許失效連接上的任務轉移到另外的鏈接上,使所有操作能夠繼續。
iSCSI錯誤恢複分四種類型:
1 命令範圍內的恢複(Recovery
within-command) 之所以稱之爲命令範圍內(within-command),是因爲這些錯誤發生在Data PDU或者R2T
PDU上,對這類錯誤進行處理,只需重傳那些被丟棄的Data PDU或R2T PDU,命令無需被重傳就能被正常恢複。
2 連接範圍內的恢複(Recovery within-connection) 當錯誤發生在Cmd PDU與Statu PDU中的情況屬於該類,稱之爲連接範圍內是因爲可能通過重傳這些丟棄的命令或狀態來恢複錯誤,而無需關閉或重啓出現數據錯誤的連接。
3 連接恢複(Connection Recovery) 處理連接TCP/IP失效的情況,使得失效連接上的任務能夠被其它正常的連接接管,整個會話過程(Session)並不因爲某連接的失效而中斷。
4 會話恢複(Session Recovery) 這裏所謂的恢複,就是當錯誤發生時,關閉當前的Session,然後在相同的Initiator與Target間建立起新的會話過程(Session)。
iSCSI錯誤恢複的級別
iSCSI錯誤恢複分爲三級:Recovery Level 0, Recovery Level 1, Recovery Level
2。其中,Level 0相對於會話恢複(Session Recovery),協議中明確要求實現它;Level 1包括
命令範圍內的恢複(Recovery within-command)與連接範圍內的恢複(Recovery
within-connection),是針對CRC校驗失敗的處理;Recovery Level 2對應於連接恢複(Connection
Recovery)。
除Level 0必須實現外,其它兩級均爲可選實現,但當高一級的錯誤恢複被實現時,其低能的錯誤恢複也必須被實現。當高級的錯誤恢複無法處理當前的錯誤時,均可交由0級錯誤去處理。即錯誤超出iSCSI的恢複能力時,Session被重啓。
錯誤恢複級別0 (Error Rrecovery Level 0)
該級別提供最低的錯誤恢複保障:當錯誤發生時,Session只能被終止並隨後被重建,之前所有的任務被放棄,相關的狀態也全部被清理,TCP連接被關閉,除持久操作被保存外,一切都不被記憶。
Session的關閉通常由Initiator向Target發送logout
PDU引起。Target接收到該PDU後,執行session的清理工作,並等待initiator端重新執行login建立起新session。在關
閉Session的最後,Initiator與Target都會返回一個狀態報告至各自的SCSI層,通告會話已被終止。
Session的重啓還可能通過另外的兩種方式實現。一是Initiator並不顯式地logout,而是等待一個DefaultTime2Wait
超時;二是執行新的login操作並在login
PDU中指定ISID而清零TSIH值。不論是哪種方式,都能使target感知,session應該被重啓。
錯誤恢複級別1 (Error Rrecovery Level 1)
該級別的錯誤恢複是針對CRC校驗失敗的,由於iSCSI中PDU的種類繁多,錯誤出現在不同種類的PDU中時有不同的處理方式,因而有些複雜(個人
認爲是整個iSCSI協議中最複雜的東東了)。要更好地理解這一級別的錯誤恢複機制,需要先對iSCSI PDU格式及序列號有一定的了解。
Initiator使用CmdSN標識自己下達給Target端的每一個命令,Target使用ExpCmdSN向Initiator確認哪些命令已經被執行。CmdSN在Session範圍內可見,每條命令正常執行後增1。
Target使用StatSN標識每一個返回給Initiator的狀態,Initator使用ExpStatSN向Tatget確認哪此狀態已經被
正確接收。StatSN在連接範圍內可見,執行完一條命令後,Target會向Initator發送一個狀態,每正常發送一個狀態,StatSN增1。
Target/Initiator使用DataSN標識每一個發往對方的數據包,Initiator/Target使用ExpDataSN向對方確認哪些數據包已經被正常接收。DataSN在每次數據傳輸開始被置0,正常發送一個Data PDU,DataSN增1。
Target使用R2TSN標識每一個發往Initator的R2T PDU,R2T PDU用於target向initiator請求數據(write命令中使用)。每個write指令中,R2TSN被初始化爲零,隨發送的R2T數而遞增。
Initiator使用SNACK Request
PDU要求target重傳某個丟失的PDU序列,如狀態,R2T,數據。在read大量數據的時候,SNACK也可被作爲initiator對
target某個數據PDU的正面確認(target在Data-In PDU設置了A bit明確要求initiator這麽做)。
由於在錯誤恢複級別1下不存在連接失效的情況,故也不應該存在數據包的丟失。下面內容中所提及的『丟失』,是指PDU因CRC校驗失敗無法識別而被initiator/target丟棄。
CRC校驗失敗可能發生在PDU頭部(Header Digest)也可能發生在數據段(Data Digest)。Data Digest校驗失敗的處理相對簡單,這裏先討論數據段出錯的情況。
在read指令中,如果initiator檢測到Data Digest檢驗錯誤,會向target發向一個SNACK要求數據重發;
在write指令中,倘若target檢測到Data Digest錯誤,它向initiator发生一个Reject
PDU通知其数据出错,随后发送R2T向initiator重新請求數據,或者終止當前任務並通知initiator重發該命令或者重啓session.
數據校驗錯誤一般能立即被恢複,因爲target與initiator都能及時地檢測到它並採取明確的動作:拒絕並要求重傳。另外,Data
Digest錯誤也可能當做Header
Digest錯誤來處理,這時接收方只需簡單地丟棄出錯的PDU,通訊的兩方將在隨後發現序列號的缺失而採取相應的措施,這樣,對數據的恢複過程被延遲。
爲了避免這種延遲而導致上層協議超時的發生,iSCSI規定如果某條連接上較長一段時間內不再有數據或命令的發出,應當在數據流後追加一個NOP
PDU,讓通訊相方能夠及時檢測到序列號的丟失。
Header Digest校驗錯誤意味著PDU中所有的序列號不再可用,PDU邊界也無法確認,無論是initiator還是target端,大多數情況下只需簡單地丟棄該包,另一方將會在隨後的PDU序列號中檢測到數據包的丟失,從而重發或者要求對方重發它們。
Initiator使用CmdSN与target返回的ExpCmd检测包含SCSI命令的PDU是否有丢失。若Initiator发现arget返
回的ExpCmdSN值小于自己预料值,则他认定CmdSN等于ExpCmdSN值的那个命令被丢失,应该当重发它们。正常情况下,每接收一条SCSI命
令,target将ExpCmd增1,若SCSI命令PDU出错,ExpCmd保持不变,从而可以向initiator指明哪条命令被丢弃。
再如,当一个Data-Out
PDU被target检测到错误而被丢弃时,target不增加它的DataSN值,当它收到另一个(无错误的)Data-Out
PDU时,就会发现Data序号不连续,从而可能发送一个R2T
PDU要求initiator重发这个被丢弃的数据包。这里需要理解的是,既然target已经知道Data-Out
PDU出错了并丢弃了它,为什么不立即发送R2T要求重传数据,而是要等到收到下一个数据包才开始请求重发?这是因为在Header
Digest出错的情况下,PDU中的DataSN已经无效,无法判断它属于哪个序列。虽然连接忠诚与TCP共同保证了write指令的数据流在同一条连
接上按序到达target端,但依然有这样的情况:initiator认为某个Data-Out
PDU丢失了,而target实际已经正确接收到了它,initiator重传这个重复的PDU的时候恰好出现Header
Digest错误,这种情况下target根本就不需要发送R2T,因为它下一个接收到的Data-Out PDU序列是连续的。
对其它序列号丢失的处理也差不多,不再一一讨论(和TCP的相关机制差不多)。更为复杂的情形是当那些用来做错误恢复的PDU(如SNACK)也出现
了错误,iSCSI有相应的策略来处理它们,但并不总在它错误恢复的能力范围之内,这时,可能只要交由Level
1去处理,即重新启动会话过程(session)。
錯誤恢複級別2 (Error Rrecovery Level 2)
錯誤恢複級別2處理TCP連接失效的情況。有多種方式可讓iSCSI征測到連接的失效:
1 Transport錯誤,如調用Send/Recv失敗;
2 命令或者回應序列存在間隙而久久(限定時間內)不能被填充,連接可能已失效;
3 ping失敗(NOP無回應);
一旦發現某條連接失效(或者被認爲失效),該級別的錯誤處理試圖通過其它的鏈接接管失效鏈接上的所有任務使會話(session)能夠繼續正常維持。
另外,Initiator也有可能接收到Target的異步消息通知其關閉並重建某個鏈接(target發現該鏈接失效了),此時,被中斷的任務也應該由
錯誤恢複例程轉移到新建的鏈接上來。
iSCSI中有一個被稱之爲連接忠誠(connection allegiance)的概念,即與某條命令相關的數據和狀態,在同一條連接上發出,其回應信息也應該在下達該命令的鏈接上被返回。錯誤恢複Level 2實質是處理失效鏈接上任務的連接忠誠的重分配。
爲了達成這個目標,initiator在關閉失效連接後(對該鏈接執行logout),可能會新建另一條連接,也可以使用session內其它的鏈接
(如果有),向target發向Management Function Request PDU(該PDU中的Function字段被設置爲TASK
REASSIGN),通知其將原連接上所有任務的連接忠誠一一轉移。原連接上的不同任務可能被分發到不同的鏈接上,針對某個任務的Management
Function Request
PDU從哪個鏈接上發出,其連接忠誠被轉移到哪個連接上來。隨後,各任務在接管它的連接上被繼續。如果創建了新的連接,則新建立的鏈接接管原連接上的所有
任務;否則,任務由其它的鏈接接管。一旦某任務被某鏈接所接管,所有針對該任務的回應都應該在該連接上從target傳回。
Initiator可能不顯示執行logout而是指定CID執行連接的re-login重啓某鏈接。此時,新連接與原連接CID號相同,但連接忠誠依然需要通過Management Function Request PDU重分配到新鏈接上來。
級別2的錯誤恢複使得某條鏈接的失效不必導致整個會話過程(session)中斷,iSCSI自行保證了因連接失效而中斷的任務在另外的連接上繼續而無需驚動SCSI層,前提是錯誤恢複在SCSI層未超時前完成。
阅读(1074) | 评论(0) | 转发(0) |