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