iSCSI - E.2.3. 대상 알고리즘

목록

E.2.3. Target Algorithms

E.2.3. 타겟 알고리즘

Receive-a-In-PDU(Connection, CurrentPDU) { check-basic-validity(CurrentPDU); if (Header-Digest-Bad) discard, return; Retrieve TCB for CurrentPDU.InitiatorTaskTag. if (CurrentPDU.type == Data) { Retrieve TContext from CurrentPDU.TargetTransferTag; if (Data-Digest-Bad) { Build-And-Send-Reject(Connection, CurrentPDU, Payload-Digest-Error); Note the missing data PDUs in MissingDataRange[]. send-recovery-R2T = TRUE; } else { if (current DataSN is not expected) { Note the missing data PDUs in MissingDataRange[]. send-recovery-R2T = TRUE; } if (CurrentPDU.Fbit == TRUE) { if (current PDU is solicited) { Decrement TCB.ActiveR2Ts. } if ((current PDU is unsolicited and data received is less than I/O length and data received is less than FirstBurstLength) or (current PDU is solicited and the length of this burst is less than expected)) { send-recovery-R2T = TRUE; Note the missing data in MissingDataRange[]. } } } } Increment TContext.ExpectedDataSN. if (send-recovery-R2T is TRUE and task is not already considered failed) { if (operational ErrorRecoveryLevel > 0) { Increment TCB.ActiveR2Ts. if (operational ErrorRecoveryLevel > 0) { Create a data-descriptor for the data burst from MissingDataRange. Build-And-Send-R2T(Connection, data-descriptor, TCB); } else { if (current PDU is the last unsolicited) TCB.Reason = "Not enough unsolicited data"; else TCB.Reason = "Protocol service CRC error"; } } if (TCB.ActiveR2Ts == 0) { Build-And-Send-Status(Connection, TCB); } } else if (CurrentPDU.type == SNACK) { snack-failure = FALSE; if (operational ErrorRecoveryLevel > 0) { if (CurrentPDU.type == Data/R2T) { if (the request is satisfiable) { if (request for Data) { Create a data-descriptor for the data burst from BegRun and RunLength. Build-And-Send-A-Data-Burst(Connection, data-descriptor, TCB); } else { /* R2T */ Create a data-descriptor for the data burst from BegRun and RunLength. Build-And-Send-R2T(Connection, data-descriptor, TCB); } } else { snack-failure = TRUE; } } else if (CurrentPDU.type == status) { Handle-Status-SNACK-request(Connection, CurrentPDU); } else if (CurrentPDU.type == DataACK) { Consider all data upto CurrentPDU.BegRun as acknowledged. Free up the retransmission resources for that data. } else if (CurrentPDU.type == R-Data SNACK) { Create a data descriptor for a data burst covering all unacknowledged data. Build-And-Send-A-Data-Burst(Connection, data-descriptor, TCB); TCB.SNACK_Tag = CurrentPDU.SNACK_Tag; if (there's no more data to send) { Build-And-Send-Status(Connection, TCB); } } } else { /* operational ErrorRecoveryLevel = 0 */ snack-failure = TRUE; } if (snack-failure == TRUE) { Build-And-Send-Reject(Connection, CurrentPDU, SNACK-Reject); if (TCB.StatusXferd != TRUE) { TCB.Reason = "SNACK Rejected"; Build-And-Send-Status(Connection, TCB); } } } else { /* REST UNRELATED TO WITHIN-COMMAND-RECOVERY, NOT SHOWN */ } } Transfer-Context-Timeout-Handler(TContext) { Retrieve TCB and Connection from TContext. Decrement TCB.ActiveR2Ts. if (operational ErrorRecoveryLevel > 0 and task is not already considered failed) { Note the missing data PDUs in MissingDataRange[]. Create a data-descriptor for the data burst from MissingDataRange[]. Build-And-Send-R2T(Connection, data-descriptor, TCB); } else { TCB.Reason = "Protocol service CRC error"; if (TCB.ActiveR2Ts = 0) { Build-And-Send-Status(Connection, TCB); } } }