diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 5db77dd..54260a6 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -2,6 +2,7 @@ iscsi-test tool support Copyright (C) 2012 by Lee Duncan + Copyright (C) 2014 Ronnie Sahlberg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,8 +64,102 @@ int readonly; int sbc3_support; int maximum_transfer_length; +int no_medium_ascqs[3] = { + SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT, + SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN, + SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED +}; +int lba_oob_ascqs[1] = { + SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE +}; +int invalid_cdb_ascqs[1] = { + SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB +}; +int write_protect_ascqs[1] = { + SCSI_SENSE_ASCQ_WRITE_PROTECTED +}; + int (*real_iscsi_queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); +static const char *scsi_status_str(int status) +{ + switch(status) { + case SCSI_STATUS_GOOD: return "SUCCESS"; + case SCSI_STATUS_CHECK_CONDITION: return "CHECK_CONDITION"; + case SCSI_STATUS_CONDITION_MET: return "CONDITIONS_MET"; + case SCSI_STATUS_BUSY: return "BUSY"; + case SCSI_STATUS_RESERVATION_CONFLICT: return "RESERVATION_CONFLICT"; + case SCSI_STATUS_TASK_SET_FULL: return "TASK_SET_FULL"; + case SCSI_STATUS_ACA_ACTIVE: return "ACA_ACTIVE"; + case SCSI_STATUS_TASK_ABORTED: return "TASK_ABORTED"; + } + return "UNKNOWN"; +} + +static int check_result(const char *opcode, struct iscsi_context *iscsi, + struct scsi_task *task, + int status, enum scsi_sense_key key, + int *ascq, int num_ascq) +{ + int ascq_ok; + + if (task == NULL) { + logging(LOG_NORMAL, "[FAILED] Failed to send %s command: " + "%s", opcode, iscsi_get_error(iscsi)); + return -1; + } + if (task->status == SCSI_STATUS_CHECK_CONDITION + && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST + && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { + logging(LOG_NORMAL, "[SKIPPED] %s is not implemented.", + opcode); + return -2; + } + if (status == SCSI_STATUS_GOOD && task->status != SCSI_STATUS_GOOD) { + logging(LOG_NORMAL, "[FAILED] %s command failed with " + "sense. %s", opcode, iscsi_get_error(iscsi)); + return -1; + } + if (status != SCSI_STATUS_GOOD && task->status == SCSI_STATUS_GOOD) { + logging(LOG_NORMAL, "[FAILED] %s successful but should " + "have failed with %s(0x%02x)/%s(0x%04x)", + opcode, + scsi_sense_key_str(key), key, + scsi_sense_ascq_str(ascq[0]), ascq[0]); + return -1; + } + /* did we get any of the expected ASCQs ?*/ + if (status == SCSI_STATUS_CHECK_CONDITION) { + int i; + for (i = 0; i < num_ascq; i++) { + if (ascq[i] == task->sense.ascq) { + ascq_ok = 1; + } + } + if (num_ascq == 0) { + ascq_ok = 1; + } + } + if (status == SCSI_STATUS_CHECK_CONDITION && + (task->status != status + || task->sense.key != key + || !ascq_ok)) { + logging(LOG_NORMAL, "[FAILED] %s failed with wrong sense. " + "Should have failed with %s(0x%02x)/%s(0x%04x)" + "but failed with Sense:%s\n", + opcode, + scsi_sense_key_str(key), key, + scsi_sense_ascq_str(ascq[0]), ascq[0], + iscsi_get_error(iscsi)); + return -1; + } + logging(LOG_VERBOSE, "[OK] %s returned %s %s(0x%02x) %s(0x%04x)", + opcode, scsi_status_str(status), + scsi_sense_key_str(task->sense.key), task->sense.key, + scsi_sense_ascq_str(task->sense.ascq), task->sense.ascq); + return 0; +} + void logging(int level, const char *format, ...) { va_list ap; diff --git a/test-tool/iscsi-support.h b/test-tool/iscsi-support.h index 78c41fc..1a1805e 100644 --- a/test-tool/iscsi-support.h +++ b/test-tool/iscsi-support.h @@ -29,6 +29,18 @@ extern const char *initiatorname1; extern const char *initiatorname2; extern const char *tgt_url; +#define EXPECT_STATUS_GOOD SCSI_STATUS_GOOD, SCSI_SENSE_NO_SENSE, NULL, 0 +#define EXPECT_NO_MEDIUM SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_NOT_READY, no_medium_ascqs, 3 +#define EXPECT_LBA_OOB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, lba_oob_ascqs, 1 +#define EXPECT_INVALID_FIELD_IN_CDB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, invalid_cdb_ascqs, 1 +#define EXPECT_MISCOMPARE SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_MISCOMPARE, 0, 0 +#define EXPECT_WRITE_PROTECTED SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_DATA_PROTECTION, write_protect_ascqs, 1 + +int no_medium_ascqs[3]; +int lba_oob_ascqs[1]; +int invalid_cdb_ascqs[1]; +int write_protect_ascqs[1]; + extern int loglevel; #define LOG_SILENT 0 #define LOG_NORMAL 1