summaryrefslogtreecommitdiffstats
path: root/sys/dev/iscsi
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-01-03 13:08:08 +0000
committermav <mav@FreeBSD.org>2015-01-03 13:08:08 +0000
commit2952feb3ad9cd929b2aeb20e2746b63042e042df (patch)
treea5b23d1902be7132085a8641947312f3920b7e1a /sys/dev/iscsi
parent5823747ac5f8823fb07d435374acaade6456d1ef (diff)
downloadFreeBSD-src-2952feb3ad9cd929b2aeb20e2746b63042e042df.zip
FreeBSD-src-2952feb3ad9cd929b2aeb20e2746b63042e042df.tar.gz
MFC r275864: Make sequence numbers checks more strict.
While we don't support MCS, hole in received sequence numbers may mean only PDU loss. While we don't support lost PDU recovery, terminate the connection to avoid stuck commands. While there, improve handling of sequence numbers wrap after 2^32 PDUs.
Diffstat (limited to 'sys/dev/iscsi')
-rw-r--r--sys/dev/iscsi/iscsi.c49
-rw-r--r--sys/dev/iscsi/iscsi_proto.h3
2 files changed, 31 insertions, 21 deletions
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index c823c0a..ed49835 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -197,7 +197,7 @@ iscsi_pdu_prepare(struct icl_pdu *request)
* Data-Out PDU does not contain CmdSN.
*/
if (bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
- if (is->is_cmdsn > is->is_maxcmdsn &&
+ if (ISCSI_SNGT(is->is_cmdsn, is->is_maxcmdsn) &&
(bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) {
/*
* Current MaxCmdSN prevents us from sending any more
@@ -206,8 +206,10 @@ iscsi_pdu_prepare(struct icl_pdu *request)
* or by maintenance thread.
*/
#if 0
- ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %d, ExpCmdSN %d, MaxCmdSN %d, opcode 0x%x",
- is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn, bhssc->bhssc_opcode);
+ ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %u, "
+ "ExpCmdSN %u, MaxCmdSN %u, opcode 0x%x",
+ is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn,
+ bhssc->bhssc_opcode);
#endif
return (true);
}
@@ -616,7 +618,7 @@ iscsi_pdu_update_statsn(const struct icl_pdu *response)
{
const struct iscsi_bhs_data_in *bhsdi;
struct iscsi_session *is;
- uint32_t expcmdsn, maxcmdsn;
+ uint32_t expcmdsn, maxcmdsn, statsn;
is = PDU_SESSION(response);
@@ -635,26 +637,27 @@ iscsi_pdu_update_statsn(const struct icl_pdu *response)
*/
if (bhsdi->bhsdi_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
(bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) {
- if (ntohl(bhsdi->bhsdi_statsn) < is->is_statsn) {
- ISCSI_SESSION_WARN(is,
- "PDU StatSN %d >= session StatSN %d, opcode 0x%x",
- is->is_statsn, ntohl(bhsdi->bhsdi_statsn),
- bhsdi->bhsdi_opcode);
+ statsn = ntohl(bhsdi->bhsdi_statsn);
+ if (statsn != is->is_statsn && statsn != (is->is_statsn + 1)) {
+ /* XXX: This is normal situation for MCS */
+ ISCSI_SESSION_WARN(is, "PDU 0x%x StatSN %u != "
+ "session ExpStatSN %u (or + 1); reconnecting",
+ bhsdi->bhsdi_opcode, statsn, is->is_statsn);
+ iscsi_session_reconnect(is);
}
- is->is_statsn = ntohl(bhsdi->bhsdi_statsn);
+ if (ISCSI_SNGT(statsn, is->is_statsn))
+ is->is_statsn = statsn;
}
expcmdsn = ntohl(bhsdi->bhsdi_expcmdsn);
maxcmdsn = ntohl(bhsdi->bhsdi_maxcmdsn);
- /*
- * XXX: Compare using Serial Arithmetic Sense.
- */
- if (maxcmdsn + 1 < expcmdsn) {
- ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d + 1 < PDU ExpCmdSN %d; ignoring",
+ if (ISCSI_SNLT(maxcmdsn + 1, expcmdsn)) {
+ ISCSI_SESSION_DEBUG(is,
+ "PDU MaxCmdSN %u + 1 < PDU ExpCmdSN %u; ignoring",
maxcmdsn, expcmdsn);
} else {
- if (maxcmdsn > is->is_maxcmdsn) {
+ if (ISCSI_SNGT(maxcmdsn, is->is_maxcmdsn)) {
is->is_maxcmdsn = maxcmdsn;
/*
@@ -663,15 +666,19 @@ iscsi_pdu_update_statsn(const struct icl_pdu *response)
*/
if (!STAILQ_EMPTY(&is->is_postponed))
cv_signal(&is->is_maintenance_cv);
- } else if (maxcmdsn < is->is_maxcmdsn) {
- ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d < session MaxCmdSN %d; ignoring",
+ } else if (ISCSI_SNLT(maxcmdsn, is->is_maxcmdsn)) {
+ /* XXX: This is normal situation for MCS */
+ ISCSI_SESSION_DEBUG(is,
+ "PDU MaxCmdSN %u < session MaxCmdSN %u; ignoring",
maxcmdsn, is->is_maxcmdsn);
}
- if (expcmdsn > is->is_expcmdsn) {
+ if (ISCSI_SNGT(expcmdsn, is->is_expcmdsn)) {
is->is_expcmdsn = expcmdsn;
- } else if (expcmdsn < is->is_expcmdsn) {
- ISCSI_SESSION_DEBUG(is, "PDU ExpCmdSN %d < session ExpCmdSN %d; ignoring",
+ } else if (ISCSI_SNLT(expcmdsn, is->is_expcmdsn)) {
+ /* XXX: This is normal situation for MCS */
+ ISCSI_SESSION_DEBUG(is,
+ "PDU ExpCmdSN %u < session ExpCmdSN %u; ignoring",
expcmdsn, is->is_expcmdsn);
}
}
diff --git a/sys/dev/iscsi/iscsi_proto.h b/sys/dev/iscsi/iscsi_proto.h
index 97d73a7..46572ce 100644
--- a/sys/dev/iscsi/iscsi_proto.h
+++ b/sys/dev/iscsi/iscsi_proto.h
@@ -38,6 +38,9 @@
#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1]
#endif
+#define ISCSI_SNGT(x, y) ((int32_t)(x) - (int32_t)(y) > 0)
+#define ISCSI_SNLT(x, y) ((int32_t)(x) - (int32_t)(y) < 0)
+
#define ISCSI_BHS_SIZE 48
#define ISCSI_HEADER_DIGEST_SIZE 4
#define ISCSI_DATA_DIGEST_SIZE 4
OpenPOWER on IntegriCloud