
org.jscsi.parser.tmf.TaskManagementFunctionRequestParser Maven / Gradle / Ivy
/**
* Copyright (c) 2012, University of Konstanz, Distributed Systems Group All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
* distribution. * Neither the name of the University of Konstanz nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jscsi.parser.tmf;
import java.util.HashMap;
import java.util.Map;
import org.jscsi.exception.InternetSCSIException;
import org.jscsi.parser.BasicHeaderSegment;
import org.jscsi.parser.Constants;
import org.jscsi.parser.InitiatorMessageParser;
import org.jscsi.parser.ProtocolDataUnit;
import org.jscsi.parser.datasegment.DataSegmentFactory.DataSegmentFormat;
import org.jscsi.utils.Utils;
/**
* TaskManagementFunctionRequestParser
*
* This class parses a Task Management Function Request message defined in the iSCSI Standard (RFC3720).
*
*
TotalAHSLength and DataSegmentLength
For this PDU TotalAHSLength and DataSegmentLength MUST be
* 0
.
*
*
LUN
This field is required for functions that address a specific LU (ABORT TASK, CLEAR TASK SET, ABORT TASK
* SET, CLEAR ACA, LOGICAL UNIT RESET) and is reserved in all others.
*
*
* @author Volker Wildi
*/
public final class TaskManagementFunctionRequestParser extends InitiatorMessageParser {
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* This enumeration defines all valid function codes, which are defined in the iSCSI standard (RFC3720).
*/
public static enum FunctionCode {
/**
* This is an artificial function code, which is only used to indicate a not set function code.
*/
UNSET((byte) 0),
/** Aborts the task identified by the Referenced Task Tag field. */
ABORT_TASK((byte) 1),
/** Aborts all Tasks issued via this session on the logical unit. */
ABORT_TASK_SET((byte) 2),
/** Clears the Auto Contingent Allegiance condition. */
CLEAR_ACA((byte) 3),
CLEAR_TASK_SET((byte) 4),
LUN_RESET((byte) 5),
TARGET_WARM_RESET((byte) 6),
TARGET_COLD_RESET((byte) 7),
TASK_REASSIGN((byte) 8);
private byte value;
private static Map mapping;
static {
FunctionCode.mapping = new HashMap();
for (FunctionCode s : values()) {
FunctionCode.mapping.put(s.value, s);
}
}
private FunctionCode (final byte newValue) {
value = newValue;
}
/**
* Returns the value of this enumeration.
*
* @return The value of this enumeration.
*/
public final byte value () {
return value;
}
/**
* Returns the constant defined for the given value
.
*
* @param value The value to search for.
* @return The constant defined for the given value
. Or null
, if this value is not
* defined by this enumeration.
*/
public static final FunctionCode valueOf (final byte value) {
return FunctionCode.mapping.get(value);
}
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** The function code. */
private FunctionCode functionCode;
/** The referenced task tag. */
private int referencedTaskTag;
/** The referenced command sequence number. */
private int refCmdSN;
/** The expected data sequence number. */
private int expDataSN;
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* Default constructor, creates a new, empty TaskManagementFunctionRequestParser
object.
*
* @param initProtocolDataUnit The reference ProtocolDataUnit
instance, which contains this
* TaskManagementFunctionRequestParser
subclass object.
*/
public TaskManagementFunctionRequestParser (final ProtocolDataUnit initProtocolDataUnit) {
super(initProtocolDataUnit);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public final String toString () {
final StringBuilder sb = new StringBuilder(Constants.LOG_INITIAL_SIZE);
// Utils.printField(sb, "Function", functionCode.value(), 1);
Utils.printField(sb, "LUN", logicalUnitNumber, 1);
Utils.printField(sb, "Referenced Task Tag", referencedTaskTag, 1);
sb.append(super.toString());
Utils.printField(sb, "RefCmdSN", refCmdSN, 1);
Utils.printField(sb, "ExpDataSN", expDataSN, 1);
return sb.toString();
}
/** {@inheritDoc} */
@Override
public final DataSegmentFormat getDataSegmentFormat () {
return DataSegmentFormat.NONE;
}
/** {@inheritDoc} */
@Override
public final void clear () {
super.clear();
functionCode = FunctionCode.UNSET;
referencedTaskTag = 0x00000000;
refCmdSN = 0x00000000;
expDataSN = 0x00000000;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* For recovery purposes, the iSCSI target and initiator maintain a data acknowledgement reference number - the
* first input DataSN number unacknowledged by the initiator. When issuing a new command, this number is set to
* 0
. If the function is TASK REASSIGN, which establishes a new connection allegiance for a previously
* issued Read or Bidirectional command, ExpDataSN
will contain an updated data acknowledgement
* reference number or the value 0
; the latter indicating that the data acknowledgement reference
* number is unchanged. The initiator MUST discard any data PDUs from the previous execution that it did not
* acknowledge and the target MUST transmit all Data-In PDUs (if any) starting with the data acknowledgement
* reference number. The number of retransmitted PDUs may or may not be the same as the original transmission
* depending on if there was a change in MaxRecvDataSegmentLength in the reassignment. The target MAY also send no
* more Data-In PDUs if all data has been acknowledged.
*
* The value of ExpDataSN
MUST be 0
or higher than the DataSN
of the last
* acknowledged Data-In PDU, but not larger than DataSN+1
of the last Data-In PDU sent by the target.
* Any other value MUST be ignored by the target.
*
* For other functions this field is reserved.
*
*
* @return The expected data sequence number of this TaskManagementFunctionRequestParser
object.
*/
public final int getExpDataSN () {
return expDataSN;
}
/**
* The Task Management functions provide an initiator with a way to explicitly control the execution of one or more
* Tasks (SCSI and iSCSI tasks). The Task Management function codes are listed below. For a more detailed
* description of SCSI task management, see [SAM2].
*
*
*
* Function Code
* Description
*
*
* 1
* ABORT TASK - aborts the task identified by the Referenced Task Tag field.
*
*
* 2
* ABORT TASK SET - aborts all Tasks issued via this session on the logical unit.
*
*
* 3
* CLEAR ACA - clears the Auto Contingent Allegiance condition.
*
*
* 4
* CLEAR TASK SET - aborts all Tasks in the appropriate task set as defined by the TST field in the Control mode
* page (see [SPC3]).
*
*
* 5
* LOGICAL UNIT RESET
*
*
* 6
* TARGET WARM RESET
*
*
* 7
* TARGET COLD RESET
*
*
* 8
* TASK REASSIGN - reassigns connection allegiance for the task identified by the Referenced Task Tag field to
* this connection, thus resuming the iSCSI exchanges for the task.
*
*
*
* For all these functions, the Task Management function response MUST be returned as detailed in Section 10.6 Task
* Management Function Response. All these functions apply to the referenced tasks regardless of whether they are
* proper SCSI tasks or tagged iSCSI operations. Task management requests must act on all the commands from the same
* session having a CmdSN lower than the task management CmdSN. LOGICAL UNIT RESET, TARGET WARM RESET and TARGET
* COLD RESET may affect commands from other sessions or commands from the same session with CmdSN equal or
* exceeding CmdSN.
*
* If the task management request is marked for immediate delivery, it must be considered immediately for execution,
* but the operations involved (all or part of them) may be postponed to allow the target to receive all relevant
* tasks. According to [SAM2], for all the tasks covered by the Task Management response (i.e., with CmdSN lower
* than the task management command CmdSN) but except the Task Management response to a TASK REASSIGN, additional
* responses MUST NOT be delivered to the SCSI layer after the Task Management response. The iSCSI initiator MAY
* deliver to the SCSI layer all responses received before the Task Management response (i.e., it is a matter of
* implementation if the SCSI responses, received before the Task Management response but after the task management
* request was issued, are delivered to the SCSI layer by the iSCSI layer in the initiator). The iSCSI target MUST
* ensure that no responses for the tasks covered by a task management function are delivered to the iSCSI initiator
* after the Task Management response except for a task covered by a TASK REASSIGN.
*
* For ABORT TASK SET and CLEAR TASK SET, the issuing initiator MUST continue to respond to all valid target
* transfer tags (received via R2T, Text Response, NOP-In, or SCSI Data-In PDUs) related to the affected task set,
* even after issuing the task management request. The issuing initiator SHOULD however terminate (i.e., by setting
* the F-bit to 1) these response sequences as quickly as possible. The target on its part MUST wait for responses
* on all affected target transfer tags before acting on either of these two task management requests. In case all
* or part of the response sequence is not received (due to digest errors) for a valid TTT, the target MAY treat it
* as a case of within-command error recovery class (see Section 6.1.4.1 Recovery Within-command) if it is
* supporting ErrorRecoveryLevel >= 1, or alternatively may drop the connection to complete the requested task set
* function.
*
* If an ABORT TASK is issued for a task created by an immediate command then RefCmdSN MUST be that of the Task
* Management request itself (i.e., CmdSN and RefCmdSN are equal); otherwise RefCmdSN MUST be set to the CmdSN of
* the task to be aborted (lower than CmdSN).
*
* If the connection is still active (it is not undergoing an implicit or explicit logout), ABORT TASK MUST be
* issued on the same connection to which the task to be aborted is allegiant at the time the Task Management
* Request is issued. If the connection is implicitly or explicitly logged out (i.e., no other request will be
* issued on the failing connection and no other response will be received on the failing connection), then an ABORT
* TASK function request may be issued on another connection. This Task Management request will then establish a new
* allegiance for the command to be aborted as well as abort it (i.e., the task to be aborted will not have to be
* retried or reassigned, and its status, if issued but not acknowledged, will be reissued followed by the Task
* Management response).
*
* At the target an ABORT TASK function MUST NOT be executed on a Task Management request; such a request MUST
* result in Task Management response of "Function rejected".
*
* For the LOGICAL UNIT RESET function, the target MUST behave as dictated by the Logical Unit Reset function in
* [SAM2].
*
* The implementation of the TARGET WARM RESET function and the TARGET COLD RESET function is OPTIONAL and when
* implemented, should act as described below. The TARGET WARM RESET is also subject to SCSI access controls on the
* requesting initiator as defined in [SPC3]. When authorization fails at the target, the appropriate response as
* described in Section 10.6 Task Management Function Response MUST be returned by the target. The TARGET COLD RESET
* function is not subject to SCSI access controls, but its execution privileges may be managed by iSCSI mechanisms
* such as login authentication.
*
* When executing the TARGET WARM RESET and TARGET COLD RESET functions, the target cancels all pending operations
* on all Logical Units known by the issuing initiator. Both functions are equivalent to the Target Reset function
* specified by [SAM2]. They can affect many other initiators logged in with the servicing SCSI target port.
*
* The target MUST treat the TARGET COLD RESET function additionally as a power on event, thus terminating all of
* its TCP connections to all initiators (all sessions are terminated). For this reason, the Service Response
* (defined by [SAM2]) for this SCSI task management function may not be reliably delivered to the issuing initiator
* port. For the TASK REASSIGN function, the target should reassign the connection allegiance to this new connection
* (and thus resume iSCSI exchanges for the task). TASK REASSIGN MUST ONLY be received by the target after the
* connection on which the command was previously executing has been successfully logged-out. The Task Management
* response MUST be issued before the reassignment becomes effective. For additional usage semantics see Section 6.2
* Retry and Reassign in Recovery.
*
* At the target a TASK REASSIGN function request MUST NOT be executed to reassign the connection allegiance of a
* Task Management function request, an active text negotiation task, or a Logout task; such a request MUST result
* in Task Management response of "Function rejected".
*
* TASK REASSIGN MUST be issued as an immediate command.
*
* @return The function code of this TaskManagementFunctionRequestParser
object.
*/
public final FunctionCode getFunction () {
return functionCode;
}
/**
* If an ABORT TASK is issued for a task created by an immediate command then RefCmdSN MUST be that of the Task
* Management request itself (i.e., CmdSN
and RefCmdSN
are equal).
*
* For an ABORT TASK of a task created by non-immediate command RefCmdSN
MUST be set to the
* CmdSN
of the task identified by the Referenced Task Tag field. Targets must use this field as
* described in section 10.6.1 when the task identified by the Referenced Task Tag field is not with the target.
*
* Otherwise, this field is reserved.
*
* @return The referenced command sequence number of this TaskManagementFunctionRequestParser
object.
*/
public final int getRefCmdSN () {
return refCmdSN;
}
/**
* The Initiator Task Tag of the task to be aborted for the ABORT TASK function or reassigned for the TASK REASSIGN
* function. For all the other functions this field MUST be set to the reserved value 0xffffffff
.
*
* @return The referenced task tag of this TaskManagementFunctionRequestParser
object.
*/
public final int getReferencedTaskTag () {
return referencedTaskTag;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final void deserializeBytes1to3 (final int line) throws InternetSCSIException {
functionCode = FunctionCode.valueOf((byte) (line & Constants.SECOND_BYTE_MASK));
Utils.isReserved(line & Constants.LAST_TWO_BYTES_MASK);
}
/** {@inheritDoc} */
@Override
protected final void deserializeBytes20to23 (final int line) throws InternetSCSIException {
referencedTaskTag = line;
}
/** {@inheritDoc} */
@Override
protected final void deserializeBytes32to35 (final int line) throws InternetSCSIException {
refCmdSN = line;
}
/** {@inheritDoc} */
@Override
protected final void deserializeBytes36to39 (final int line) throws InternetSCSIException {
expDataSN = line;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final void checkIntegrity () throws InternetSCSIException {
String exceptionMessage;
do {
BasicHeaderSegment bhs = protocolDataUnit.getBasicHeaderSegment();
if (bhs.getTotalAHSLength() != 0) {
exceptionMessage = "TotalAHSLength must be 0!";
break;
}
if (bhs.getDataSegmentLength() != 0) {
exceptionMessage = "DataSegmentLength must be 0!";
break;
}
if (functionCode != FunctionCode.ABORT_TASK && functionCode != FunctionCode.ABORT_TASK_SET && functionCode != FunctionCode.CLEAR_ACA) {
Utils.isReserved(logicalUnitNumber);
}
// message is checked correctly
return;
} while (false);
throw new InternetSCSIException(exceptionMessage);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final int serializeBytes1to3 () {
return functionCode.value() << Constants.TWO_BYTES_SHIFT;
}
/** {@inheritDoc} */
@Override
protected final int serializeBytes20to23 () {
return referencedTaskTag;
}
/** {@inheritDoc} */
@Override
protected final int serializeBytes32to35 () {
return refCmdSN;
}
/** {@inheritDoc} */
@Override
protected final int serializeBytes36to39 () {
return expDataSN;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
}