xref: /spdk/test/unit/lib/iscsi/common.c (revision 6f338d4bf3a8a91b7abe377a605a321ea2b05bf7)
1 #include "iscsi/task.h"
2 #include "iscsi/iscsi.h"
3 #include "iscsi/conn.h"
4 
5 #include "spdk/env.h"
6 #include "spdk/sock.h"
7 #include "spdk_cunit.h"
8 
9 #include "spdk/log.h"
10 #include "spdk_internal/mock.h"
11 
12 #include "scsi/scsi_internal.h"
13 
14 SPDK_LOG_REGISTER_COMPONENT(iscsi)
15 
16 TAILQ_HEAD(, spdk_iscsi_pdu) g_write_pdu_list = TAILQ_HEAD_INITIALIZER(g_write_pdu_list);
17 
18 static bool g_task_pool_is_empty = false;
19 static bool g_pdu_pool_is_empty = false;
20 static uint32_t g_conn_read_len;
21 static bool g_conn_read_data_digest = false;
22 static uint32_t g_data_digest;
23 
24 struct spdk_iscsi_task *
25 iscsi_task_get(struct spdk_iscsi_conn *conn,
26 	       struct spdk_iscsi_task *parent,
27 	       spdk_scsi_task_cpl cpl_fn)
28 {
29 	struct spdk_iscsi_task *task;
30 
31 	if (g_task_pool_is_empty) {
32 		return NULL;
33 	}
34 
35 	task = calloc(1, sizeof(*task));
36 	if (!task) {
37 		return NULL;
38 	}
39 
40 	task->conn = conn;
41 	task->scsi.cpl_fn = cpl_fn;
42 	if (parent) {
43 		parent->scsi.ref++;
44 		task->parent = parent;
45 		task->tag = parent->tag;
46 		task->lun_id = parent->lun_id;
47 		task->scsi.dxfer_dir = parent->scsi.dxfer_dir;
48 		task->scsi.transfer_len = parent->scsi.transfer_len;
49 		task->scsi.lun = parent->scsi.lun;
50 		task->scsi.cdb = parent->scsi.cdb;
51 		task->scsi.target_port = parent->scsi.target_port;
52 		task->scsi.initiator_port = parent->scsi.initiator_port;
53 		if (conn && (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
54 			conn->data_in_cnt++;
55 		}
56 	}
57 
58 	task->scsi.iovs = &task->scsi.iov;
59 	return task;
60 }
61 
62 void
63 spdk_scsi_task_put(struct spdk_scsi_task *task)
64 {
65 	free(task);
66 }
67 
68 void
69 iscsi_put_pdu(struct spdk_iscsi_pdu *pdu)
70 {
71 	if (!pdu) {
72 		return;
73 	}
74 
75 	pdu->ref--;
76 	if (pdu->ref < 0) {
77 		CU_FAIL("negative ref count");
78 		pdu->ref = 0;
79 	}
80 
81 	if (pdu->ref == 0) {
82 		if (pdu->data && !pdu->data_from_mempool) {
83 			free(pdu->data);
84 		}
85 		free(pdu);
86 	}
87 }
88 
89 struct spdk_iscsi_pdu *
90 iscsi_get_pdu(struct spdk_iscsi_conn *conn)
91 {
92 	struct spdk_iscsi_pdu *pdu;
93 
94 	assert(conn != NULL);
95 	if (g_pdu_pool_is_empty) {
96 		return NULL;
97 	}
98 
99 	pdu = malloc(sizeof(*pdu));
100 	if (!pdu) {
101 		return NULL;
102 	}
103 
104 	memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs));
105 	pdu->ref = 1;
106 	pdu->conn = conn;
107 
108 	return pdu;
109 }
110 
111 DEFINE_STUB_V(spdk_scsi_task_process_null_lun, (struct spdk_scsi_task *task));
112 
113 DEFINE_STUB_V(spdk_scsi_task_process_abort, (struct spdk_scsi_task *task));
114 
115 void
116 spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task)
117 {
118 	struct spdk_scsi_lun *lun;
119 
120 	lun = TAILQ_FIRST(&dev->luns);
121 	SPDK_CU_ASSERT_FATAL(lun != NULL);
122 
123 	TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
124 }
125 
126 DEFINE_STUB(spdk_scsi_dev_find_port_by_id, struct spdk_scsi_port *,
127 	    (struct spdk_scsi_dev *dev, uint64_t id), NULL);
128 
129 DEFINE_STUB_V(spdk_scsi_dev_queue_mgmt_task,
130 	      (struct spdk_scsi_dev *dev, struct spdk_scsi_task *task));
131 
132 const char *
133 spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev)
134 {
135 	if (dev != NULL) {
136 		return dev->name;
137 	}
138 
139 	return NULL;
140 }
141 
142 DEFINE_STUB(spdk_scsi_dev_construct, struct spdk_scsi_dev *,
143 	    (const char *name, const char **bdev_name_list,
144 	     int *lun_id_list, int num_luns, uint8_t protocol_id,
145 	     void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
146 	     void *hotremove_ctx),
147 	    NULL);
148 
149 DEFINE_STUB_V(spdk_scsi_dev_destruct,
150 	      (struct spdk_scsi_dev *dev, spdk_scsi_dev_destruct_cb_t cb_fn, void *cb_arg));
151 
152 DEFINE_STUB(spdk_scsi_dev_add_port, int,
153 	    (struct spdk_scsi_dev *dev, uint64_t id, const char *name), 0);
154 
155 DEFINE_STUB(iscsi_drop_conns, int,
156 	    (struct spdk_iscsi_conn *conn, const char *conn_match, int drop_all),
157 	    0);
158 
159 DEFINE_STUB(spdk_scsi_dev_delete_port, int,
160 	    (struct spdk_scsi_dev *dev, uint64_t id), 0);
161 
162 DEFINE_STUB_V(shutdown_iscsi_conns, (void));
163 
164 DEFINE_STUB_V(iscsi_conns_request_logout, (struct spdk_iscsi_tgt_node *target, int pg_tag));
165 
166 DEFINE_STUB(iscsi_get_active_conns, int, (struct spdk_iscsi_tgt_node *target), 0);
167 
168 void
169 iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
170 {
171 	struct spdk_iscsi_task *iscsi_task;
172 
173 	if (scsi_task != NULL) {
174 		iscsi_task = iscsi_task_from_scsi_task(scsi_task);
175 		if (iscsi_task->parent && (iscsi_task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
176 			assert(iscsi_task->conn->data_in_cnt > 0);
177 			iscsi_task->conn->data_in_cnt--;
178 		}
179 
180 		free(iscsi_task);
181 	}
182 }
183 
184 DEFINE_STUB_V(iscsi_task_mgmt_cpl, (struct spdk_scsi_task *scsi_task));
185 
186 #define MAKE_DIGEST_WORD(BUF, CRC32C) \
187         (   ((*((uint8_t *)(BUF)+0)) = (uint8_t)((uint32_t)(CRC32C) >> 0)), \
188             ((*((uint8_t *)(BUF)+1)) = (uint8_t)((uint32_t)(CRC32C) >> 8)), \
189             ((*((uint8_t *)(BUF)+2)) = (uint8_t)((uint32_t)(CRC32C) >> 16)), \
190             ((*((uint8_t *)(BUF)+3)) = (uint8_t)((uint32_t)(CRC32C) >> 24)))
191 
192 int
193 iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes, void *buf)
194 {
195 	uint32_t *data = buf;
196 	int i;
197 
198 	if (g_conn_read_data_digest) {
199 		MAKE_DIGEST_WORD(buf, g_data_digest);
200 		return ISCSI_DIGEST_LEN;
201 	}
202 
203 	/* Limit the length to 4 bytes multiples. */
204 	SPDK_CU_ASSERT_FATAL((bytes % 4) == 0);
205 
206 	for (i = 0; i < bytes; i += 4) {
207 		data[i / 4] = g_conn_read_len + i;
208 	}
209 
210 	g_conn_read_len += bytes;
211 
212 	return bytes;
213 }
214 
215 int
216 iscsi_conn_readv_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt)
217 {
218 	int i, len = 0;
219 
220 	for (i = 0; i < iovcnt; i++) {
221 		len += iov[i].iov_len;
222 	}
223 
224 	return len;
225 }
226 
227 void
228 iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
229 		     iscsi_conn_xfer_complete_cb cb_fn, void *cb_arg)
230 {
231 	TAILQ_INSERT_TAIL(&g_write_pdu_list, pdu, tailq);
232 }
233 
234 DEFINE_STUB_V(iscsi_conn_logout, (struct spdk_iscsi_conn *conn));
235 
236 DEFINE_STUB_V(spdk_scsi_task_set_status,
237 	      (struct spdk_scsi_task *task, int sc, int sk, int asc, int ascq));
238 
239 void
240 spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
241 {
242 	SPDK_CU_ASSERT_FATAL(task->iovs != NULL);
243 	task->iovs[0].iov_base = data;
244 	task->iovs[0].iov_len = len;
245 }
246