TESTS: Add some REPORT SUPPORTED OPCODES tests
Add a simple test that it works or is not implemented. Add a RCTD test to verify that with this flag clear we get command descriptors without CTDP set and with it set we get command descriptors with CTDP set and a timeout descriptor
This commit is contained in:
@@ -255,6 +255,8 @@ bin_iscsi_test_cu_SOURCES = test-tool/iscsi-test-cu.c \
|
||||
test-tool/test_readcapacity16_protection.c \
|
||||
test-tool/test_readcapacity16_simple.c \
|
||||
test-tool/test_readonly_sbc.c \
|
||||
test-tool/test_report_supported_opcodes_simple.c \
|
||||
test-tool/test_report_supported_opcodes_rctd.c \
|
||||
test-tool/test_reserve6_simple.c \
|
||||
test-tool/test_reserve6_2initiators.c \
|
||||
test-tool/test_reserve6_logout.c \
|
||||
|
||||
@@ -739,24 +739,24 @@ struct scsi_get_lba_status {
|
||||
|
||||
struct scsi_op_timeout_descriptor {
|
||||
uint16_t descriptor_length;
|
||||
uint8_t reserved;
|
||||
uint8_t command_specific;
|
||||
uint32_t nominal_processing_timeout;
|
||||
uint32_t recommended_timeout;
|
||||
|
||||
};
|
||||
struct scsi_command_descriptor {
|
||||
uint8_t op_code;
|
||||
uint8_t reserved1;
|
||||
uint16_t service_action;
|
||||
uint8_t reserved2;
|
||||
uint8_t reserved3;
|
||||
uint16_t cdb_length;
|
||||
struct scsi_op_timeout_descriptor to[0];
|
||||
uint8_t opcode;
|
||||
uint16_t sa;
|
||||
uint8_t ctdp;
|
||||
uint8_t servactv;
|
||||
uint16_t cdb_len;
|
||||
|
||||
/* only present if CTDP==1 */
|
||||
struct scsi_op_timeout_descriptor to;
|
||||
};
|
||||
|
||||
struct scsi_report_supported_op_codes {
|
||||
uint32_t num_descriptors;
|
||||
int num_descriptors;
|
||||
struct scsi_command_descriptor descriptors[0];
|
||||
};
|
||||
|
||||
@@ -911,39 +911,37 @@ EXTERN void *scsi_cdb_unmarshall(struct scsi_task *task, enum scsi_opcode opcode
|
||||
unsigned char *scsi_task_get_data_in_buffer(struct scsi_task *task, uint32_t pos, ssize_t *count);
|
||||
unsigned char *scsi_task_get_data_out_buffer(struct scsi_task *task, uint32_t pos, ssize_t *count);
|
||||
|
||||
EXTERN struct scsi_task *scsi_cdb_compareandwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_get_lba_status(uint64_t starting_lba, uint32_t alloc_len);
|
||||
EXTERN struct scsi_task *scsi_cdb_orwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_persistent_reserve_in(enum scsi_persistent_in_sa sa, uint16_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persistent_out_scope scope, enum scsi_persistent_out_type type, void *params);
|
||||
EXTERN struct scsi_task *scsi_cdb_prefetch10(uint32_t lba, int num_blocks, int immed, int group);
|
||||
EXTERN struct scsi_task *scsi_cdb_prefetch16(uint64_t lba, int num_blocks, int immed, int group);
|
||||
EXTERN struct scsi_task *scsi_cdb_preventallow(int prevent);
|
||||
EXTERN struct scsi_task *scsi_cdb_read6(uint32_t lba, uint32_t xferlen, int blocksize);
|
||||
EXTERN struct scsi_task *scsi_cdb_read10(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_read12(uint32_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_read16(uint64_t lba, uint32_t xferlen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_write12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_readcapacity16(void);
|
||||
EXTERN struct scsi_task *scsi_cdb_report_supported_opcodes(int rctd, int options, enum scsi_opcode opcode, int sa, uint32_t alloc_len);
|
||||
EXTERN struct scsi_task *scsi_cdb_serviceactionin16(enum scsi_service_action_in sa, uint32_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_startstopunit(int immed, int pcm, int pc, int no_flush, int loej, int start);
|
||||
EXTERN struct scsi_task *scsi_cdb_preventallow(int prevent);
|
||||
EXTERN struct scsi_task *scsi_cdb_orwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_compareandwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_synchronizecache10(int lba, int num_blocks, int syncnv, int immed);
|
||||
EXTERN struct scsi_task *scsi_cdb_synchronizecache16(uint64_t lba, uint32_t num_blocks, int syncnv, int immed);
|
||||
EXTERN struct scsi_task *scsi_cdb_unmap(int anchor, int group, uint16_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_verify10(uint32_t lba, uint32_t xferlen, int vprotect, int dpo, int bytchk, int blocksize);
|
||||
EXTERN struct scsi_task *scsi_cdb_verify12(uint32_t lba, uint32_t xferlen, int vprotect, int dpo, int bytchk, int blocksize);
|
||||
EXTERN struct scsi_task *scsi_cdb_verify16(uint64_t lba, uint32_t xferlen, int vprotect, int dpo, int bytchk, int blocksize);
|
||||
|
||||
EXTERN struct scsi_task *scsi_cdb_synchronizecache10(int lba, int num_blocks,
|
||||
int syncnv, int immed);
|
||||
EXTERN struct scsi_task *scsi_cdb_synchronizecache16(uint64_t lba, uint32_t num_blocks,
|
||||
int syncnv, int immed);
|
||||
EXTERN struct scsi_task *scsi_cdb_serviceactionin16(enum scsi_service_action_in sa, uint32_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_readcapacity16(void);
|
||||
EXTERN struct scsi_task *scsi_cdb_get_lba_status(uint64_t starting_lba, uint32_t alloc_len);
|
||||
EXTERN struct scsi_task *scsi_cdb_unmap(int anchor, int group, uint16_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_persistent_reserve_in(enum scsi_persistent_in_sa sa, uint16_t xferlen);
|
||||
EXTERN struct scsi_task *scsi_cdb_persistent_reserve_out(enum scsi_persistent_out_sa sa, enum scsi_persistent_out_scope scope, enum scsi_persistent_out_type type, void *params);
|
||||
EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_write12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_writesame10(int wrprotect, int anchor, int unmap, uint32_t lba, int group, uint16_t num_blocks);
|
||||
EXTERN struct scsi_task *scsi_cdb_writesame16(int wrprotect, int anchor, int unmap, uint64_t lba, int group, uint32_t num_blocks);
|
||||
EXTERN struct scsi_task *scsi_cdb_prefetch10(uint32_t lba, int num_blocks, int immed, int group);
|
||||
EXTERN struct scsi_task *scsi_cdb_prefetch16(uint64_t lba, int num_blocks, int immed, int group);
|
||||
EXTERN struct scsi_task *scsi_cdb_report_supported_opcodes(int rctd, int options, enum scsi_opcode opcode, int sa, uint32_t alloc_len);
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
EXTERN struct scsi_task *scsi_cdb_writeverify16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number);
|
||||
|
||||
|
||||
void *scsi_malloc(struct scsi_task *task, size_t size);
|
||||
|
||||
|
||||
@@ -806,12 +806,6 @@ scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
scsi_maintenancein_return_timeouts(const struct scsi_task *task)
|
||||
{
|
||||
return task->cdb[2] & 0x80;
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
scsi_maintenancein_sa(const struct scsi_task *task)
|
||||
{
|
||||
@@ -841,9 +835,7 @@ static void *
|
||||
scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
|
||||
{
|
||||
struct scsi_report_supported_op_codes *rsoc;
|
||||
struct scsi_command_descriptor *desc, *datain;
|
||||
uint32_t len, i;
|
||||
int return_timeouts, desc_size;
|
||||
int len, i;
|
||||
|
||||
switch (scsi_maintenancein_sa(task)) {
|
||||
case SCSI_REPORT_SUPPORTED_OP_CODES:
|
||||
@@ -852,37 +844,52 @@ scsi_maintenancein_datain_unmarshall(struct scsi_task *task)
|
||||
}
|
||||
|
||||
len = task_get_uint32(task, 0);
|
||||
rsoc = scsi_malloc(task, sizeof(struct scsi_report_supported_op_codes) + len);
|
||||
/* len / 8 is not always correct since if CTDP==1 then the
|
||||
* descriptor is 20 bytes in size intead of 8.
|
||||
* It doesnt matter here though since it just means we would
|
||||
* allocate more descriptors at the end of the structure than
|
||||
* we strictly need. This avoids having to traverse the
|
||||
* datain buffer twice.
|
||||
*/
|
||||
rsoc = scsi_malloc(task,
|
||||
offsetof(struct scsi_report_supported_op_codes,
|
||||
descriptors) +
|
||||
len / 8 * sizeof(struct scsi_command_descriptor));
|
||||
if (rsoc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* Does the descriptor include command timeout info? */
|
||||
return_timeouts = scsi_maintenancein_return_timeouts(task);
|
||||
|
||||
/* Size of descriptor depends on whether timeout included. */
|
||||
desc_size = sizeof (struct scsi_command_descriptor);
|
||||
if (return_timeouts) {
|
||||
desc_size += sizeof (struct scsi_op_timeout_descriptor);
|
||||
}
|
||||
rsoc->num_descriptors = len / desc_size;
|
||||
rsoc->num_descriptors = 0;
|
||||
i = 4;
|
||||
while (len >= 8) {
|
||||
struct scsi_command_descriptor *desc;
|
||||
|
||||
desc = &rsoc->descriptors[rsoc->num_descriptors++];
|
||||
desc->opcode = task_get_uint8(task, i);
|
||||
desc->sa = task_get_uint16(task, i + 2);
|
||||
desc->ctdp = !!(task_get_uint8(task, i + 5) & 0x02);
|
||||
desc->servactv = !!(task_get_uint8(task, i + 5) & 0x01);
|
||||
desc->cdb_len = task_get_uint16(task, i + 6);
|
||||
|
||||
desc = &rsoc->descriptors[0];
|
||||
datain = (struct scsi_command_descriptor *)&task->datain.data[4];
|
||||
len -= 8;
|
||||
i += 8;
|
||||
|
||||
for (i=0; i < rsoc->num_descriptors; i++) {
|
||||
desc->op_code = datain->op_code;
|
||||
desc->service_action = ntohs(datain->service_action);
|
||||
desc->cdb_length = ntohs(datain->cdb_length);
|
||||
if (return_timeouts) {
|
||||
desc->to[0].descriptor_length = ntohs(datain->to[0].descriptor_length);
|
||||
desc->to[0].command_specific = datain->to[0].command_specific;
|
||||
desc->to[0].nominal_processing_timeout
|
||||
= ntohl(datain->to[0].nominal_processing_timeout);
|
||||
desc->to[0].recommended_timeout
|
||||
= ntohl(datain->to[0].recommended_timeout);
|
||||
/* No tiemout description */
|
||||
if (!desc->ctdp) {
|
||||
continue;
|
||||
}
|
||||
desc = (struct scsi_command_descriptor *)((char *)desc + desc_size);
|
||||
datain = (struct scsi_command_descriptor *)((char *)datain + desc_size);
|
||||
|
||||
desc->to.descriptor_length =
|
||||
task_get_uint16(task, i);
|
||||
desc->to.command_specific =
|
||||
task_get_uint8(task, i + 3);
|
||||
desc->to.nominal_processing_timeout =
|
||||
task_get_uint32(task, i + 4);
|
||||
desc->to.recommended_timeout =
|
||||
task_get_uint32(task, i + 8);
|
||||
|
||||
len -= desc->to.descriptor_length + 2;
|
||||
i += desc->to.descriptor_length + 2;
|
||||
}
|
||||
|
||||
return rsoc;
|
||||
|
||||
@@ -31,7 +31,7 @@ int T0430_report_all_supported_ops(const char *initiator, const char *url)
|
||||
struct scsi_command_descriptor *desc;
|
||||
int ret, lun;
|
||||
int full_size, desc_size;
|
||||
unsigned i;
|
||||
int i;
|
||||
|
||||
printf("0430_report_all_supported_ops:\n");
|
||||
printf("===================\n");
|
||||
@@ -108,9 +108,9 @@ int T0430_report_all_supported_ops(const char *initiator, const char *url)
|
||||
printf("=======================\n");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
printf("op:%x\tsa:%x\tcdb length:%d\n",
|
||||
rsoc->descriptors[i].op_code,
|
||||
rsoc->descriptors[i].service_action,
|
||||
rsoc->descriptors[i].cdb_length);
|
||||
rsoc->descriptors[i].opcode,
|
||||
rsoc->descriptors[i].sa,
|
||||
rsoc->descriptors[i].cdb_len);
|
||||
}
|
||||
|
||||
printf("\n[OK]\n");
|
||||
@@ -179,13 +179,13 @@ int T0430_report_all_supported_ops(const char *initiator, const char *url)
|
||||
desc = &rsoc->descriptors[0];
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
printf("op:%x\tsa:%x\tcdb_length:%d\ttimeout info: length:%d\tcommand specific:%x\tnominal processing%d\trecommended%d\n",
|
||||
desc->op_code,
|
||||
desc->service_action,
|
||||
desc->cdb_length,
|
||||
desc->to[0].descriptor_length,
|
||||
desc->to[0].command_specific,
|
||||
desc->to[0].nominal_processing_timeout,
|
||||
desc->to[0].recommended_timeout);
|
||||
desc->opcode,
|
||||
desc->sa,
|
||||
desc->cdb_len,
|
||||
desc->to.descriptor_length,
|
||||
desc->to.command_specific,
|
||||
desc->to.nominal_processing_timeout,
|
||||
desc->to.recommended_timeout);
|
||||
desc = (struct scsi_command_descriptor *)((char *)desc +
|
||||
desc_size);
|
||||
}
|
||||
|
||||
@@ -2759,6 +2759,48 @@ release6(struct iscsi_context *iscsi, int lun)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int report_supported_opcodes(struct iscsi_context *iscsi, int lun, int rctd, int options, int opcode, int sa, int alloc_len, struct scsi_task **save_task)
|
||||
{
|
||||
struct scsi_task *task;
|
||||
|
||||
logging(LOG_VERBOSE, "Send REPORT_SUPPORTED_OPCODE RCTD:%d OPTIONS:%d "
|
||||
"OPCODE:%d SA:%d ALLOC_LEN:%d",
|
||||
rctd, options, opcode, sa, alloc_len);
|
||||
|
||||
task = iscsi_report_supported_opcodes_sync(iscsi, lun,
|
||||
rctd, options, opcode, sa, alloc_len);
|
||||
if (task == NULL) {
|
||||
logging(LOG_NORMAL, "[FAILED] Failed to send "
|
||||
"REPORT_SUPPORTED_OPCODES command: %s",
|
||||
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] REPORT_SUPPORTED_OPCODES is not "
|
||||
"implemented on target");
|
||||
scsi_free_scsi_task(task);
|
||||
return -2;
|
||||
}
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_NORMAL, "[FAILED] REPORT_SUPPORTED_OPCODES "
|
||||
"command: failed with sense. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
scsi_free_scsi_task(task);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (save_task != NULL) {
|
||||
*save_task = task;
|
||||
} else {
|
||||
scsi_free_scsi_task(task);
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "[OK] REPORT_SUPPORTED_OPCODES returned SUCCESS.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
reserve6(struct iscsi_context *iscsi, int lun)
|
||||
{
|
||||
|
||||
@@ -243,6 +243,7 @@ int readcapacity10(struct iscsi_context *iscsi, int lun, uint32_t lba, int pmi);
|
||||
int readcapacity10_nomedium(struct iscsi_context *iscsi, int lun, uint32_t lba, int pmi);
|
||||
int readcapacity16(struct iscsi_context *iscsi, int lun, int alloc_len);
|
||||
int readcapacity16_nomedium(struct iscsi_context *iscsi, int lun, int alloc_len);
|
||||
int report_supported_opcodes(struct iscsi_context *iscsi, int lun, int rctd, int options, int opcode, int sa, int alloc_len, struct scsi_task **save_task);
|
||||
int release6(struct iscsi_context *iscsi, int lun);
|
||||
int reserve6(struct iscsi_context *iscsi, int lun);
|
||||
int reserve6_conflict(struct iscsi_context *iscsi, int lun);
|
||||
|
||||
@@ -221,6 +221,12 @@ static CU_TestInfo tests_readonly[] = {
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
static CU_TestInfo tests_report_supported_opcodes[] = {
|
||||
{ (char *)"ReportSupportedOpcodesSimple", test_report_supported_opcodes_simple },
|
||||
{ (char *)"ReportSupportedOpcodesRCTD", test_report_supported_opcodes_rctd },
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
static CU_TestInfo tests_reserve6[] = {
|
||||
{ (char *)"Reserve6Simple", test_reserve6_simple },
|
||||
{ (char *)"Reserve6_2Initiators", test_reserve6_2initiators },
|
||||
@@ -403,6 +409,8 @@ static CU_SuiteInfo scsi_suites[] = {
|
||||
tests_readcapacity16 },
|
||||
{ (char *)"ReadOnly", test_setup, test_teardown,
|
||||
tests_readonly },
|
||||
{ (char *)"ReportSupportedOpcodes", test_setup, test_teardown,
|
||||
tests_report_supported_opcodes },
|
||||
{ (char *)"Reserve6", test_setup, test_teardown,
|
||||
tests_reserve6 },
|
||||
{ (char *)"StartStopUnit", test_setup, test_teardown,
|
||||
@@ -505,6 +513,8 @@ static CU_SuiteInfo all_suites[] = {
|
||||
tests_readcapacity16 },
|
||||
{ (char *)"ReadOnly", test_setup, test_teardown,
|
||||
tests_readonly },
|
||||
{ (char *)"ReportSupportedOpcodes", test_setup, test_teardown,
|
||||
tests_report_supported_opcodes },
|
||||
{ (char *)"Reserve6", test_setup, test_teardown,
|
||||
tests_reserve6 },
|
||||
{ (char *)"StartStopUnit", test_setup, test_teardown,
|
||||
@@ -577,6 +587,8 @@ static CU_SuiteInfo scsi_usb_sbc_suites[] = {
|
||||
tests_readcapacity16 },
|
||||
{ (char *)"ReadOnly", test_setup, test_teardown,
|
||||
tests_readonly },
|
||||
{ (char *)"ReportSupportedOpcodes", test_setup, test_teardown,
|
||||
tests_report_supported_opcodes },
|
||||
{ (char *)"Reserve6", test_setup, test_teardown,
|
||||
tests_reserve6 },
|
||||
{ (char *)"TestUnitReady", test_setup, test_teardown,
|
||||
|
||||
@@ -138,6 +138,9 @@ void test_readcapacity16_simple(void);
|
||||
|
||||
void test_readonly_sbc(void);
|
||||
|
||||
void test_report_supported_opcodes_simple(void);
|
||||
void test_report_supported_opcodes_rctd(void);
|
||||
|
||||
void test_reserve6_simple(void);
|
||||
void test_reserve6_2initiators(void);
|
||||
void test_reserve6_logout(void);
|
||||
|
||||
99
test-tool/test_report_supported_opcodes_rctd.c
Normal file
99
test-tool/test_report_supported_opcodes_rctd.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-support.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
|
||||
void
|
||||
test_report_supported_opcodes_rctd(void)
|
||||
{
|
||||
int i, ret;
|
||||
struct scsi_task *rso_task;
|
||||
struct scsi_report_supported_op_codes *rsoc;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES RCTD flag");
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES report ALL opcodes "
|
||||
"without timeout descriptors");
|
||||
ret = report_supported_opcodes(iscsic, tgt_lun,
|
||||
0, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0,
|
||||
65535, &rso_task);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READ_SUPPORTED_OPCODES is not "
|
||||
"implemented.");
|
||||
CU_PASS("READ_SUPPORTED_OPCODES is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_NOT_EQUAL(rsoc, NULL);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that all returned command descriptors "
|
||||
"lack timeout description");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (rsoc->descriptors[i].ctdp) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor with "
|
||||
"CTDP set");
|
||||
CU_FAIL("[FAILED] Command descriptor with "
|
||||
"CTDP set");
|
||||
}
|
||||
}
|
||||
scsi_free_scsi_task(rso_task);
|
||||
|
||||
|
||||
logging(LOG_VERBOSE, "Test READ_SUPPORTED_OPCODES report ALL opcodes "
|
||||
"with timeout descriptors");
|
||||
ret = report_supported_opcodes(iscsic, tgt_lun,
|
||||
1, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0,
|
||||
65535, &rso_task);
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
if (ret != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
|
||||
rsoc = scsi_datain_unmarshall(rso_task);
|
||||
CU_ASSERT_NOT_EQUAL(rsoc, NULL);
|
||||
|
||||
logging(LOG_VERBOSE, "Verify that all returned command descriptors "
|
||||
"have a timeout description");
|
||||
for (i = 0; i < rsoc->num_descriptors; i++) {
|
||||
if (!rsoc->descriptors[i].ctdp) {
|
||||
logging(LOG_NORMAL, "[FAILED] Command descriptor "
|
||||
"without CTDP set");
|
||||
CU_FAIL("[FAILED] Command descriptor without "
|
||||
"CTDP set");
|
||||
}
|
||||
}
|
||||
|
||||
scsi_free_scsi_task(rso_task);
|
||||
}
|
||||
46
test-tool/test_report_supported_opcodes_simple.c
Normal file
46
test-tool/test_report_supported_opcodes_simple.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "iscsi.h"
|
||||
#include "scsi-lowlevel.h"
|
||||
#include "iscsi-support.h"
|
||||
#include "iscsi-test-cu.h"
|
||||
|
||||
|
||||
void
|
||||
test_report_supported_opcodes_simple(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||
logging(LOG_VERBOSE, "Test basic READ_SUPPORTED_OPCODES");
|
||||
|
||||
ret = report_supported_opcodes(iscsic, tgt_lun,
|
||||
0, SCSI_REPORT_SUPPORTING_OPS_ALL, 0, 0,
|
||||
1024, NULL);
|
||||
if (ret == -2) {
|
||||
logging(LOG_NORMAL, "[SKIPPED] READ_SUPPORTED_OPCODES is not "
|
||||
"implemented.");
|
||||
CU_PASS("READ_SUPPORTED_OPCODES is not implemented.");
|
||||
return;
|
||||
}
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
}
|
||||
Reference in New Issue
Block a user