INI-STATSN	16-Feb-2005	Bob Russell

	How the Initiator deals with StatSN and ExpStatSN

StatSN is the "Status Sequence Number" for a connection.
	It's purpose is to enable the initiator to detect missing response
	pdus of any type sent by the target, and to enable the initiator to
	acknowledge the acceptance of response pdus previously sent by the
	target.  A response pdu can be received by the initiator but not yet
	accepted by the initiator because that response triggers further
	work by the initiator.  For example, if the target sends a SCSI
	Response pdu for a READ command, then upon receiving it the initiator
	checks to be sure that all expected DataIn pdus have been received
	correctly.  If some have not been, then the initiator sends a SNACK
	of type 0 (Data/R2T) to request the retransmission of the missing or
	erroneous DataIn pdus belonging to that READ.  Only after all the
	retransmissions have been received correctly will the initiator
	consider the SCSI Response pdu to have been accepted.
	

All iSCSI request pdus sent by the initiator to the target carry ExpStatSN:
	0x00	NopOut
	0x01	SCSI Command
	0x02	Task Management Function Request
	0x03	Login Request (on 1st login request of a connection, valid
				only if this is a connection restart)
	0x04	Text Request
	0x05	DataOut
	0x06	Logout Request
	0x10	SNACK Request

Most iSCSI response pdus sent by the target to the initiator carry StatSN,
and the counter maintained by the target is normally incremented by 1 after
each response pdu is sent, except as noted:
	0x20	NopIn (but when ITT=0xffffffff, StatSN is not advanced)
	0x21	SCSI Response
	0x22	Task Management Function Response
	0x23	Login Response (carries StatSN only when StatusClass == 0.
				1st login response of a connection carries the
				starting StatSN number for the new connection)
	0x24	Text Response
	0x25	DataIn (carries StatSN only when S bit == 1)
	0x26	Logout Response
	0x31	R2T (StatSN is not advanced)
	0x32	Asynchronous Message
	0x3f	Reject

On the target:
      > each connection (struct iscsi_conn) has the field:
		__u32	stat_sn;
	which stores the StatSN counter for that connection.
	This field is initialized to 0 when a new connection is created.
	This field is incremented by 1 after sending each new response pdu
	that carries it (a DataIn pdu with S == 0, the NopIn pdu when
	ITT=0xffffff, and R2T pdu do not carry it).
	This field is not incremented when a response pdu is retransmitted
	for any reason.

      > each command (struct iscsi_cmnd) has the field:
		__u32	stat_sn;
	which holds the ExpStatSN field from the command pdu received from
	the initiator (in host byte order).

On the initiator:
      > each connection (struct connection) has the fields:

		__u32	last_rcvd_stat_sn
	which is the most recent StatSN value received in a response pdu
	from the target.  This is used by the initiator to detect missing
	response pdus from the target.

		__u32	exp_stat_sn;
	which is the ExpStatSN to be sent in the next request pdu that is
	the first pdu of a new command to be sent to the target.  This is
	used by the initiator to acknowledge accepted request pdus to the
	target.

		__u32	outstanding_requests;
	which is the total number of request pdus sent to the target for
	which an expected response pdu has not yet been accepted by the
	initiator.


Steps taken by the initiator:

 0. The initiator initializes exp_stat_sn from the StatSN field received in
    the last Login Response pdu.  It initializes last_rcvd_stat_sn from
    exp_stat_sn if the login phase was successful.  It initializes
    outstanding_requests to 0.

 1. When the initiator queues a new request for transmission to the target,
    and that request expects a response, it increments outstanding_requests
    by 1.  This is done in attach_pending_command() when need_itt is 1 or 2.

 2. When the initiator actually sends a pdu to the target, it copies the
    current exp_stat_sn field from the connection into the ExpStatSN field
    in the command (except for SNACK request pdus, where this is done when
    the SNACK is queued for transmission).  This is done in finalize_header().

 3. When the initiator receives any response pdu from the target in
    iscsi_initiator_rx_thread(), it checks the StatSN field in all
    response pdus except for a DataIn with S bit == 0.
	Normally this pdu's StatSN == last_rcvd_stat_sn + 1,
		in which case last_rcvd_stat_sn is set to StatSN
		(i.e., last_rcvd_stat_sn gets incremented by 1) except
		when this pdu is an R2T, or a NopIn with ITT == 0xffffffff.
	When this StatSN < last_rcvd_stat_sn + 1,
		the response pdu just received must be a retransmission,
		possibly requested by a previous SNACK.  We don't change
		any of the 3 fields, but just go ahead and process the
		response pdu.
	When this StatSN > last_rcvd_stat_sn + 1,
		if this pdu is a SCSI Response, then we deduce that there
		were missing response pdus sent by the target but not
		received by the initiator, so we go ahead and cause a
		SEQUENCE_ERR error recovery.

 4. When the initiator processes any response pdu and accepts it as a valid
    response that terminates an outstanding request, it decrements
    outstanding_requests by 1 and if the result is 0, it then sets
    	exp_stat_sn = last_rcvd_stat_sn + 1;
    this is done by calling the function accept_response(connection);
