
org.jscsi.parser.tmf.TaskManagementFunctionResponseParser Maven / Gradle / Ivy
The newest version!
/**
* 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.ProtocolDataUnit;
import org.jscsi.parser.TargetMessageParser;
import org.jscsi.parser.datasegment.DataSegmentFactory.DataSegmentFormat;
import org.jscsi.parser.logout.LogoutResponse;
import org.jscsi.utils.Utils;
/**
* This class parses a Task Management Function Response message defined in the iSCSI Standard (RFC3720).
*
*
Task Management Actions on Task Sets
The execution of ABORT TASK SET and CLEAR TASK SET Task Management
* function requests consists of the following sequence of events in the specified order on each of the entities.
*
* The initiator:
*
*
* - Issues ABORT TASK SET/CLEAR TASK SET request.
* - Continues to respond to each target transfer tag received for the affected task set.
* - Receives any responses for the tasks in the affected task set (may process them as usual because they are
* guaranteed to be valid).
* - Receives the task set management response, thus concluding all the tasks in the affected task set.
*
*
* The target:
*
*
* - Receives the ABORT TASK SET/CLEAR TASK SET request.
* - Waits for all target transfer tags to be responded to and for all affected tasks in the task set to be received.
* - Propagates the command to and receives the response from the target SCSI layer.
* - Takes note of last-sent StatSN on each of the connections in the iSCSI sessions (one or more) sharing the
* affected task set, and waits for acknowledgement of each StatSN (may solicit for acknowledgement by way of a NOP-In).
* If some tasks originate from non-iSCSI I_T_L nexi then the means by which the target insures that all affected tasks
* have returned their status to the initiator are defined by the specific protocol.
* - Sends the task set management response to the issuing initiator.
*
*
*
TotalAHSLength and DataSegmentLength
For this PDU TotalAHSLength and DataSegmentLength MUST be
* 0
.
*
* @author Volker Wildi
*/
public final class TaskManagementFunctionResponseParser extends TargetMessageParser {
/**
* This enumeration defines all valid response code, which are defined in the iSCSI Standard (RFC 3720).
*
* @author Volker Wildi
*/
public static enum ResponseCode {
/** Function complete. */
FUNCTION_COMPLETE((byte) 0),
/** Task does not exist. */
TASK_DOES_NOT_EXIST((byte) 1),
/** LUN does not exist. */
LUN_DOES_NOT_EXIST((byte) 2),
/** Task still allegiant. */
TASK_STILL_ALLEGIANT((byte) 3),
/** Task allegiance reassignment not supported. */
TASK_ALLEGIANCE_REASSIGNMENT_NOT_SUPPORTED((byte) 4),
/** Task management function not supported. */
TASK_MANAGEMENT_FUNCTION_NOT_SUPPORTED((byte) 5),
/** Function authorization failed. */
FUNCTION_AUTHORIZATION_FAILED((byte) 6),
/** Function rejected. */
FUNCTION_REJECTED((byte) 255);
private byte value;
private static Map mapping;
static {
ResponseCode.mapping = new HashMap();
for (ResponseCode s : values()) {
ResponseCode.mapping.put(s.value, s);
}
}
private ResponseCode (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 ResponseCode valueOf (final byte value) {
return ResponseCode.mapping.get(value);
}
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** The response code. */
private ResponseCode response;
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* Default constructor, creates a new, empty TaskManagementFunctionResponseParser
object.
*
* @param initProtocolDataUnit The reference ProtocolDataUnit
instance, which contains this
* TaskManagementFunctionResponseParser
subclass object.
*/
public TaskManagementFunctionResponseParser (final ProtocolDataUnit initProtocolDataUnit) {
super(initProtocolDataUnit);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public final String toString () {
final StringBuilder sb = new StringBuilder(Constants.LOG_INITIAL_SIZE);
Utils.printField(sb, "Response", response.value(), 1);
sb.append(super.toString());
return sb.toString();
}
/** {@inheritDoc} */
@Override
public final DataSegmentFormat getDataSegmentFormat () {
return DataSegmentFormat.NONE;
}
/** {@inheritDoc} */
@Override
public final void clear () {
super.clear();
response = null;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* The target provides a Response, which may take on the following values:
*
*
* Response Code
* Description
*
*
* 0
* Function complete.
*
*
* 1
* Task does not exist.
*
*
* 2
* LUN does not exist.
*
*
* 3
* Task still allegiant.
*
*
* 4
* Task allegiance reassignment not supported.
*
*
* 5
* Task management function not supported.
*
*
* 6
* Function authorization failed.
*
*
* 255
* Function rejected.
*
*
*
*
* All other values are reserved.
*
* For a discussion on usage of response codes 3
and 4
, see Section 6.2.2 Allegiance
* Reassignment.
*
* For the TARGET COLD RESET and TARGET WARM RESET functions, the target cancels all pending operations across all
* Logical Units known to the issuing initiator. For the TARGET COLD RESET function, the target MUST then close all
* of its TCP connections to all initiators (terminates all sessions).
*
* The mapping of the response code into a SCSI service response code value, if needed, is outside the scope of this
* document. However, in symbolic terms Response values 0 and 1 map to the SCSI service response of FUNCTION
* COMPLETE. All other Response values map to the SCSI service response of FUNCTION REJECTED. If a Task Management
* function response PDU does not arrive before the session is terminated, the SCSI service response is SERVICE
* DELIVERY OR TARGET FAILURE.
*
* The response to ABORT TASK SET and CLEAR TASK SET MUST only be issued by the target after all of the commands
* affected have been received by the target, the corresponding task management functions have been executed by the
* SCSI target, and the delivery of all responses delivered until the task management function completion have been
* confirmed (acknowledged through ExpStatSN) by the initiator on all connections of this session. For the exact
* timeline of events, refer to Section 10.6.2 Task Management Actions on Task Sets.
*
* For the ABORT TASK function,
*
* - If the Referenced Task Tag identifies a valid task leading to a successful termination, then targets must
* return the "Function complete" response.
* - If the Referenced Task Tag does not identify an existing task, but if the CmdSN indicated by the RefCmdSN
* field in the Task Management function request is within the valid CmdSN window and less than the CmdSN of the
* Task Management function request itself, then targets must consider the CmdSN received and return the
* "Function complete" response.
* - If the Referenced Task Tag does not identify an existing task and if the CmdSN indicated by the RefCmdSN
* field in the Task Management function request is outside the valid CmdSN window, then targets must return the
* "Task does not exist" response.
*
*
* @return The response code of this TaskManagementFunctionResponseParser
object.
*/
public final ResponseCode getResponse () {
return response;
}
public final void setResponse (ResponseCode response) {
this.response = response;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final void deserializeBytes1to3 (final int line) throws InternetSCSIException {
Utils.isReserved(line & Constants.SECOND_BYTE_MASK);
response = ResponseCode.valueOf((byte) (line & Constants.THIRD_BYTE_MASK));
Utils.isReserved(line & Constants.FOURTH_BYTE_MASK);
}
/** {@inheritDoc} */
@Override
protected final void deserializeBytes20to23 (final int line) throws InternetSCSIException {
Utils.isReserved(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;
}
Utils.isReserved(logicalUnitNumber);
// message is checked correctly
return;
} while (false);
throw new InternetSCSIException(exceptionMessage);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final int serializeBytes1to3 () {
return response.value() << Constants.ONE_BYTE_SHIFT;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy