Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/endian.h"
9 : : #include "spdk/scsi.h"
10 : : #include "spdk_internal/cunit.h"
11 : :
12 : : #include "CUnit/Basic.h"
13 : :
14 : : #include "iscsi/iscsi.c"
15 : :
16 : : #include "../common.c"
17 : : #include "iscsi/portal_grp.h"
18 : : #include "scsi/scsi_internal.h"
19 : : #include "common/lib/test_env.c"
20 : :
21 : : #include "spdk_internal/mock.h"
22 : :
23 : : #define UT_TARGET_NAME1 "iqn.2017-11.spdk.io:t0001"
24 : : #define UT_TARGET_NAME2 "iqn.2017-11.spdk.io:t0002"
25 : : #define UT_INITIATOR_NAME1 "iqn.2017-11.spdk.io:i0001"
26 : : #define UT_INITIATOR_NAME2 "iqn.2017-11.spdk.io:i0002"
27 : : #define UT_ISCSI_TSIH 256
28 : :
29 : : struct spdk_iscsi_tgt_node g_tgt = {
30 : : .mutex = PTHREAD_MUTEX_INITIALIZER
31 : : };
32 : :
33 : : struct spdk_iscsi_tgt_node *
34 : 28 : iscsi_find_tgt_node(const char *target_name)
35 : : {
36 [ + + + + ]: 28 : if (strcasecmp(target_name, UT_TARGET_NAME1) == 0) {
37 : 24 : g_tgt.dev = NULL;
38 : 24 : return (struct spdk_iscsi_tgt_node *)&g_tgt;
39 : : } else {
40 : 4 : return NULL;
41 : : }
42 : 7 : }
43 : :
44 : : bool
45 : 24 : iscsi_tgt_node_access(struct spdk_iscsi_conn *conn,
46 : : struct spdk_iscsi_tgt_node *target,
47 : : const char *iqn, const char *addr)
48 : : {
49 [ + + + + ]: 24 : if (strcasecmp(conn->initiator_name, UT_INITIATOR_NAME1) == 0) {
50 : 20 : return true;
51 : : } else {
52 : 4 : return false;
53 : : }
54 : 6 : }
55 : :
56 [ - + - + ]: 24 : DEFINE_STUB(iscsi_tgt_node_is_redirected, bool,
57 : : (struct spdk_iscsi_conn *conn, struct spdk_iscsi_tgt_node *target,
58 : : char *buf, int buf_len),
59 : : false);
60 : :
61 [ # # # # ]: 0 : DEFINE_STUB(iscsi_send_tgts, int,
62 : : (struct spdk_iscsi_conn *conn, const char *iiqn,
63 : : const char *tiqn, uint8_t *data, int alloc_len, int data_len),
64 : : 0);
65 : :
66 [ - + - + ]: 24 : DEFINE_STUB(iscsi_tgt_node_is_destructed, bool,
67 : : (struct spdk_iscsi_tgt_node *target), false);
68 : :
69 : 0 : DEFINE_STUB_V(iscsi_portal_grp_close_all, (void));
70 : :
71 : 0 : DEFINE_STUB_V(iscsi_conn_schedule, (struct spdk_iscsi_conn *conn));
72 : :
73 : 0 : DEFINE_STUB_V(iscsi_conn_free_pdu,
74 : : (struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu));
75 : :
76 : 0 : DEFINE_STUB_V(iscsi_conn_pdu_generic_complete, (void *cb_arg));
77 : :
78 [ # # # # ]: 0 : DEFINE_STUB(iscsi_conn_handle_queued_datain_tasks, int,
79 : : (struct spdk_iscsi_conn *conn), 0);
80 : :
81 [ # # # # ]: 0 : DEFINE_STUB(iscsi_conn_abort_queued_datain_task, int,
82 : : (struct spdk_iscsi_conn *conn, uint32_t ref_task_tag), 0);
83 : :
84 [ # # # # ]: 0 : DEFINE_STUB(iscsi_conn_abort_queued_datain_tasks, int,
85 : : (struct spdk_iscsi_conn *conn, struct spdk_scsi_lun *lun,
86 : : struct spdk_iscsi_pdu *pdu), 0);
87 : :
88 [ # # # # ]: 0 : DEFINE_STUB(iscsi_chap_get_authinfo, int,
89 : : (struct iscsi_chap_auth *auth, const char *authuser, int ag_tag),
90 : : 0);
91 : :
92 [ # # # # ]: 0 : DEFINE_STUB(spdk_sock_set_recvbuf, int, (struct spdk_sock *sock, int sz), 0);
93 : :
94 : : int
95 : 0 : spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun)
96 : : {
97 : 0 : return lun->id;
98 : : }
99 : :
100 [ - + - + ]: 20 : DEFINE_STUB(spdk_scsi_lun_is_removing, bool, (const struct spdk_scsi_lun *lun),
101 : : true);
102 : :
103 : : struct spdk_scsi_lun *
104 : 208 : spdk_scsi_dev_get_lun(struct spdk_scsi_dev *dev, int lun_id)
105 : : {
106 : : struct spdk_scsi_lun *lun;
107 : :
108 [ + + ]: 208 : TAILQ_FOREACH(lun, &dev->luns, tailq) {
109 [ + - ]: 172 : if (lun->id == lun_id) {
110 : 172 : break;
111 : : }
112 : 0 : }
113 : :
114 : 208 : return lun;
115 : : }
116 : :
117 [ - + - + ]: 40 : DEFINE_STUB(spdk_scsi_lun_id_int_to_fmt, uint64_t, (int lun_id), 0);
118 : :
119 [ - + - + ]: 76 : DEFINE_STUB(spdk_scsi_lun_id_fmt_to_int, int, (uint64_t lun_fmt), 0);
120 : :
121 [ - + - + ]: 68 : DEFINE_STUB(spdk_scsi_lun_get_dif_ctx, bool,
122 : : (struct spdk_scsi_lun *lun, struct spdk_scsi_task *task,
123 : : struct spdk_dif_ctx *dif_ctx), false);
124 : :
125 : : static void
126 : 24 : alloc_mock_mobj(struct spdk_mobj *mobj, int len)
127 : : {
128 : 24 : mobj->buf = calloc(1, SPDK_BDEV_BUF_SIZE_WITH_MD(len));
129 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(mobj->buf != NULL);
130 : :
131 : 24 : g_iscsi.pdu_immediate_data_pool = (struct spdk_mempool *)100;
132 : 24 : g_iscsi.pdu_data_out_pool = (struct spdk_mempool *)200;
133 [ + - ]: 24 : if (len == SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) {
134 : 24 : mobj->mp = g_iscsi.pdu_data_out_pool;
135 : 6 : } else {
136 : 0 : mobj->mp = g_iscsi.pdu_immediate_data_pool;
137 : : }
138 : 24 : }
139 : :
140 : : static void
141 : 4 : op_login_check_target_test(void)
142 : : {
143 : 4 : struct spdk_iscsi_conn conn = {};
144 : 4 : struct spdk_iscsi_pdu rsp_pdu = {};
145 : 3 : struct spdk_iscsi_tgt_node *target;
146 : : int rc;
147 : :
148 : : /* expect success */
149 [ - + ]: 4 : snprintf(conn.initiator_name, sizeof(conn.initiator_name),
150 : : "%s", UT_INITIATOR_NAME1);
151 : :
152 : 4 : rc = iscsi_op_login_check_target(&conn, &rsp_pdu,
153 : : UT_TARGET_NAME1, &target);
154 : 4 : CU_ASSERT(rc == 0);
155 : :
156 : : /* expect failure */
157 [ - + ]: 4 : snprintf(conn.initiator_name, sizeof(conn.initiator_name),
158 : : "%s", UT_INITIATOR_NAME1);
159 : :
160 : 4 : rc = iscsi_op_login_check_target(&conn, &rsp_pdu,
161 : : UT_TARGET_NAME2, &target);
162 : 4 : CU_ASSERT(rc != 0);
163 : :
164 : : /* expect failure */
165 [ - + ]: 4 : snprintf(conn.initiator_name, sizeof(conn.initiator_name),
166 : : "%s", UT_INITIATOR_NAME2);
167 : :
168 : 4 : rc = iscsi_op_login_check_target(&conn, &rsp_pdu,
169 : : UT_TARGET_NAME1, &target);
170 : 4 : CU_ASSERT(rc != 0);
171 : 4 : }
172 : :
173 : : static void
174 : 4 : op_login_session_normal_test(void)
175 : : {
176 : 4 : struct spdk_iscsi_conn conn = {};
177 : 4 : struct spdk_iscsi_portal portal = {};
178 : 4 : struct spdk_iscsi_portal_grp group = {};
179 : 4 : struct spdk_iscsi_pdu rsp_pdu = {};
180 : : struct iscsi_bhs_login_rsp *rsph;
181 : 4 : struct spdk_iscsi_sess sess = {};
182 : 4 : struct iscsi_param param = {};
183 : : int rc;
184 : :
185 : : /* setup related data structures */
186 : 4 : rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu.bhs;
187 : 4 : rsph->tsih = 0;
188 [ - + ]: 4 : memset(rsph->isid, 0, sizeof(rsph->isid));
189 : 4 : conn.portal = &portal;
190 : 4 : portal.group = &group;
191 : 4 : conn.portal->group->tag = 0;
192 : 4 : conn.params = NULL;
193 : :
194 : : /* expect failure: NULL params for target name */
195 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
196 : : NULL, 0);
197 : 4 : CU_ASSERT(rc != 0);
198 : 4 : CU_ASSERT(rsph->status_class == ISCSI_CLASS_INITIATOR_ERROR);
199 : 4 : CU_ASSERT(rsph->status_detail == ISCSI_LOGIN_MISSING_PARMS);
200 : :
201 : : /* expect failure: incorrect key for target name */
202 : 4 : param.next = NULL;
203 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
204 : : ¶m, 0);
205 : 4 : CU_ASSERT(rc != 0);
206 : 4 : CU_ASSERT(rsph->status_class == ISCSI_CLASS_INITIATOR_ERROR);
207 : 4 : CU_ASSERT(rsph->status_detail == ISCSI_LOGIN_MISSING_PARMS);
208 : :
209 : : /* expect failure: NULL target name */
210 : 4 : param.key = "TargetName";
211 : 4 : param.val = NULL;
212 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
213 : : ¶m, 0);
214 : 4 : CU_ASSERT(rc != 0);
215 : 4 : CU_ASSERT(rsph->status_class == ISCSI_CLASS_INITIATOR_ERROR);
216 : 4 : CU_ASSERT(rsph->status_detail == ISCSI_LOGIN_MISSING_PARMS);
217 : :
218 : : /* expect failure: session not found */
219 : 4 : param.key = "TargetName";
220 : 4 : param.val = "iqn.2017-11.spdk.io:t0001";
221 [ - + ]: 4 : snprintf(conn.initiator_name, sizeof(conn.initiator_name),
222 : : "%s", UT_INITIATOR_NAME1);
223 : 4 : rsph->tsih = 1; /* to append the session */
224 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
225 : : ¶m, 0);
226 : 4 : CU_ASSERT(conn.target_port == NULL);
227 : 4 : CU_ASSERT(rc != 0);
228 : 4 : CU_ASSERT(rsph->status_class == ISCSI_CLASS_INITIATOR_ERROR);
229 : 4 : CU_ASSERT(rsph->status_detail == ISCSI_LOGIN_CONN_ADD_FAIL);
230 : :
231 : : /* expect failure: session found while tag is wrong */
232 : 4 : g_iscsi.MaxSessions = UT_ISCSI_TSIH * 2;
233 : 4 : g_iscsi.session = calloc(1, sizeof(void *) * g_iscsi.MaxSessions);
234 : 4 : g_iscsi.session[UT_ISCSI_TSIH - 1] = &sess;
235 : 4 : sess.tsih = UT_ISCSI_TSIH;
236 : 4 : rsph->tsih = UT_ISCSI_TSIH >> 8; /* to append the session */
237 : 4 : sess.tag = 1;
238 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
239 : : ¶m, 0);
240 : 4 : CU_ASSERT(conn.target_port == NULL);
241 : 4 : CU_ASSERT(rc != 0);
242 : 4 : CU_ASSERT(rsph->status_class == ISCSI_CLASS_INITIATOR_ERROR);
243 : 4 : CU_ASSERT(rsph->status_detail == ISCSI_LOGIN_CONN_ADD_FAIL);
244 : :
245 : : /* expect success: drop the session */
246 : 4 : rsph->tsih = 0; /* to create the session */
247 : 4 : g_iscsi.AllowDuplicateIsid = false;
248 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
249 : : ¶m, 0);
250 : 4 : CU_ASSERT(rc == 0);
251 : :
252 : : /* expect success: create the session */
253 : 4 : rsph->tsih = 0; /* to create the session */
254 : 4 : g_iscsi.AllowDuplicateIsid = true;
255 : 4 : rc = iscsi_op_login_session_normal(&conn, &rsp_pdu, UT_INITIATOR_NAME1,
256 : : ¶m, 0);
257 : 4 : CU_ASSERT(rc == 0);
258 : :
259 : 4 : free(g_iscsi.session);
260 : 4 : }
261 : :
262 : : static void
263 : 4 : maxburstlength_test(void)
264 : : {
265 : 4 : struct spdk_iscsi_sess sess = {};
266 : 4 : struct spdk_iscsi_conn conn = {};
267 : 4 : struct spdk_scsi_dev dev = {};
268 : 4 : struct spdk_scsi_lun lun = {};
269 : : struct spdk_iscsi_pdu *req_pdu, *data_out_pdu, *r2t_pdu;
270 : : struct iscsi_bhs_scsi_req *req;
271 : : struct iscsi_bhs_r2t *r2t;
272 : : struct iscsi_bhs_data_out *data_out;
273 : : struct spdk_iscsi_pdu *response_pdu;
274 : : int rc;
275 : :
276 : 4 : g_iscsi.MaxR2TPerConnection = DEFAULT_MAXR2T;
277 : :
278 : 4 : req_pdu = iscsi_get_pdu(&conn);
279 : 4 : data_out_pdu = iscsi_get_pdu(&conn);
280 : :
281 : 4 : sess.ExpCmdSN = 0;
282 : 4 : sess.MaxCmdSN = 64;
283 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
284 : 4 : sess.MaxBurstLength = 1024;
285 : :
286 : 4 : lun.id = 0;
287 : :
288 : 4 : TAILQ_INIT(&dev.luns);
289 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
290 : :
291 : 4 : conn.full_feature = 1;
292 : 4 : conn.sess = &sess;
293 : 4 : conn.dev = &dev;
294 : 4 : conn.state = ISCSI_CONN_STATE_RUNNING;
295 : 4 : TAILQ_INIT(&conn.write_pdu_list);
296 : 4 : TAILQ_INIT(&conn.active_r2t_tasks);
297 : :
298 : 4 : req_pdu->bhs.opcode = ISCSI_OP_SCSI;
299 : 4 : req_pdu->data_segment_len = 0;
300 : :
301 : 4 : req = (struct iscsi_bhs_scsi_req *)&req_pdu->bhs;
302 : :
303 : 4 : to_be32(&req->cmd_sn, 0);
304 : 4 : to_be32(&req->expected_data_xfer_len, 1028);
305 : 4 : to_be32(&req->itt, 0x1234);
306 : 4 : req->write_bit = 1;
307 : 4 : req->final_bit = 1;
308 : :
309 : 4 : rc = iscsi_pdu_hdr_handle(&conn, req_pdu);
310 [ + - + + : 4 : if (rc == 0 && !req_pdu->is_rejected) {
+ - ]
311 : 4 : rc = iscsi_pdu_payload_handle(&conn, req_pdu);
312 : 1 : }
313 : 4 : CU_ASSERT(rc == 0);
314 : :
315 : 4 : response_pdu = TAILQ_FIRST(&g_write_pdu_list);
316 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(response_pdu != NULL);
317 : :
318 : : /*
319 : : * Confirm that a correct R2T reply was sent in response to the
320 : : * SCSI request.
321 : : */
322 [ + - ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, response_pdu, tailq);
323 : 4 : CU_ASSERT(response_pdu->bhs.opcode == ISCSI_OP_R2T);
324 : 4 : r2t = (struct iscsi_bhs_r2t *)&response_pdu->bhs;
325 : 4 : CU_ASSERT(from_be32(&r2t->desired_xfer_len) == 1024);
326 : 4 : CU_ASSERT(from_be32(&r2t->buffer_offset) == 0);
327 : 4 : CU_ASSERT(from_be32(&r2t->itt) == 0x1234);
328 : :
329 : 4 : data_out_pdu->bhs.opcode = ISCSI_OP_SCSI_DATAOUT;
330 : 4 : data_out_pdu->bhs.flags = ISCSI_FLAG_FINAL;
331 : 4 : data_out_pdu->data_segment_len = 1028;
332 : 4 : data_out = (struct iscsi_bhs_data_out *)&data_out_pdu->bhs;
333 : 4 : data_out->itt = r2t->itt;
334 : 4 : data_out->ttt = r2t->ttt;
335 : 4 : DSET24(data_out->data_segment_len, 1028);
336 : :
337 : 4 : rc = iscsi_pdu_hdr_handle(&conn, data_out_pdu);
338 [ - + - - : 4 : if (rc == 0 && !data_out_pdu->is_rejected) {
- - ]
339 : 0 : rc = iscsi_pdu_payload_handle(&conn, data_out_pdu);
340 : 0 : }
341 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
342 : :
343 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(response_pdu->task != NULL);
344 : 4 : iscsi_task_disassociate_pdu(response_pdu->task);
345 : 4 : iscsi_task_put(response_pdu->task);
346 : 4 : iscsi_put_pdu(response_pdu);
347 : :
348 : 4 : r2t_pdu = TAILQ_FIRST(&g_write_pdu_list);
349 : 4 : CU_ASSERT(r2t_pdu != NULL);
350 [ - + ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, r2t_pdu, tailq);
351 : 4 : iscsi_put_pdu(r2t_pdu);
352 : :
353 : 4 : iscsi_put_pdu(data_out_pdu);
354 : 4 : iscsi_put_pdu(req_pdu);
355 : 4 : }
356 : :
357 : : static void
358 : 4 : underflow_for_read_transfer_test(void)
359 : : {
360 : 4 : struct spdk_iscsi_sess sess = {};
361 : 4 : struct spdk_iscsi_conn conn = {};
362 : 4 : struct spdk_iscsi_task task = {};
363 : 4 : struct spdk_scsi_dev dev = {};
364 : 4 : struct spdk_scsi_lun lun = {};
365 : : struct spdk_iscsi_pdu *pdu;
366 : : struct iscsi_bhs_scsi_req *scsi_req;
367 : : struct iscsi_bhs_data_in *datah;
368 : 4 : uint32_t residual_count = 0;
369 : :
370 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH;
371 : :
372 : 4 : conn.sess = &sess;
373 : 4 : conn.MaxRecvDataSegmentLength = 8192;
374 : :
375 : 4 : TAILQ_INIT(&dev.luns);
376 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
377 : 4 : conn.dev = &dev;
378 : :
379 : 4 : pdu = iscsi_get_pdu(&conn);
380 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
381 : :
382 : 4 : scsi_req = (struct iscsi_bhs_scsi_req *)&pdu->bhs;
383 : 4 : scsi_req->read_bit = 1;
384 : :
385 : 4 : iscsi_task_set_pdu(&task, pdu);
386 : 4 : task.parent = NULL;
387 : :
388 : 4 : task.scsi.iov.iov_base = (void *)0xF0000000;
389 : 4 : task.scsi.iovs = &task.scsi.iov;
390 : 4 : task.scsi.iovcnt = 1;
391 : 4 : task.scsi.length = 512;
392 : 4 : task.scsi.transfer_len = 512;
393 : 4 : task.bytes_completed = 512;
394 : 4 : task.scsi.data_transferred = 256;
395 : 4 : task.scsi.status = SPDK_SCSI_STATUS_GOOD;
396 : :
397 : 4 : iscsi_task_response(&conn, &task);
398 : 4 : iscsi_put_pdu(pdu);
399 : :
400 : : /*
401 : : * In this case, a SCSI Data-In PDU should contain the Status
402 : : * for the data transfer.
403 : : */
404 : 4 : to_be32(&residual_count, 256);
405 : :
406 : 4 : pdu = TAILQ_FIRST(&g_write_pdu_list);
407 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
408 : :
409 : 4 : CU_ASSERT(pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN);
410 : :
411 : 4 : datah = (struct iscsi_bhs_data_in *)&pdu->bhs;
412 : :
413 : 4 : CU_ASSERT(datah->flags == (ISCSI_DATAIN_UNDERFLOW | ISCSI_FLAG_FINAL | ISCSI_DATAIN_STATUS));
414 : 4 : CU_ASSERT(datah->res_cnt == residual_count);
415 : :
416 [ - + ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq);
417 : 4 : iscsi_put_pdu(pdu);
418 : :
419 : 4 : CU_ASSERT(TAILQ_EMPTY(&g_write_pdu_list));
420 : 4 : }
421 : :
422 : : static void
423 : 4 : underflow_for_zero_read_transfer_test(void)
424 : : {
425 : 4 : struct spdk_iscsi_sess sess = {};
426 : 4 : struct spdk_iscsi_conn conn = {};
427 : 4 : struct spdk_iscsi_task task = {};
428 : 4 : struct spdk_scsi_dev dev = {};
429 : 4 : struct spdk_scsi_lun lun = {};
430 : : struct spdk_iscsi_pdu *pdu;
431 : : struct iscsi_bhs_scsi_req *scsi_req;
432 : : struct iscsi_bhs_scsi_resp *resph;
433 : 4 : uint32_t residual_count = 0, data_segment_len;
434 : :
435 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH;
436 : :
437 : 4 : conn.sess = &sess;
438 : 4 : conn.MaxRecvDataSegmentLength = 8192;
439 : :
440 : 4 : TAILQ_INIT(&dev.luns);
441 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
442 : 4 : conn.dev = &dev;
443 : :
444 : 4 : pdu = iscsi_get_pdu(&conn);
445 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
446 : :
447 : 4 : scsi_req = (struct iscsi_bhs_scsi_req *)&pdu->bhs;
448 : 4 : scsi_req->read_bit = 1;
449 : :
450 : 4 : iscsi_task_set_pdu(&task, pdu);
451 : 4 : task.parent = NULL;
452 : :
453 : 4 : task.scsi.length = 512;
454 : 4 : task.scsi.transfer_len = 512;
455 : 4 : task.bytes_completed = 512;
456 : 4 : task.scsi.data_transferred = 0;
457 : 4 : task.scsi.status = SPDK_SCSI_STATUS_GOOD;
458 : :
459 : 4 : iscsi_task_response(&conn, &task);
460 : 4 : iscsi_put_pdu(pdu);
461 : :
462 : : /*
463 : : * In this case, only a SCSI Response PDU is expected and
464 : : * underflow must be set in it.
465 : : * */
466 : 4 : to_be32(&residual_count, 512);
467 : :
468 : 4 : pdu = TAILQ_FIRST(&g_write_pdu_list);
469 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
470 : :
471 : 4 : CU_ASSERT(pdu->bhs.opcode == ISCSI_OP_SCSI_RSP);
472 : :
473 : 4 : resph = (struct iscsi_bhs_scsi_resp *)&pdu->bhs;
474 : :
475 : 4 : CU_ASSERT(resph->flags == (ISCSI_SCSI_UNDERFLOW | 0x80));
476 : :
477 : 4 : data_segment_len = DGET24(resph->data_segment_len);
478 : 4 : CU_ASSERT(data_segment_len == 0);
479 : 4 : CU_ASSERT(resph->res_cnt == residual_count);
480 : :
481 [ - + ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq);
482 : 4 : iscsi_put_pdu(pdu);
483 : :
484 : 4 : CU_ASSERT(TAILQ_EMPTY(&g_write_pdu_list));
485 : 4 : }
486 : :
487 : : static void
488 : 4 : underflow_for_request_sense_test(void)
489 : : {
490 : 4 : struct spdk_iscsi_sess sess = {};
491 : 4 : struct spdk_iscsi_conn conn = {};
492 : 4 : struct spdk_iscsi_task task = {};
493 : 4 : struct spdk_scsi_dev dev = {};
494 : 4 : struct spdk_scsi_lun lun = {};
495 : : struct spdk_iscsi_pdu *pdu1, *pdu2;
496 : : struct iscsi_bhs_scsi_req *scsi_req;
497 : : struct iscsi_bhs_data_in *datah;
498 : : struct iscsi_bhs_scsi_resp *resph;
499 : 4 : uint32_t residual_count = 0, data_segment_len;
500 : :
501 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH;
502 : :
503 : 4 : conn.sess = &sess;
504 : 4 : conn.MaxRecvDataSegmentLength = 8192;
505 : :
506 : 4 : TAILQ_INIT(&dev.luns);
507 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
508 : 4 : conn.dev = &dev;
509 : :
510 : 4 : pdu1 = iscsi_get_pdu(&conn);
511 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
512 : :
513 : 4 : scsi_req = (struct iscsi_bhs_scsi_req *)&pdu1->bhs;
514 : 4 : scsi_req->read_bit = 1;
515 : :
516 : 4 : iscsi_task_set_pdu(&task, pdu1);
517 : 4 : task.parent = NULL;
518 : :
519 : 4 : task.scsi.iov.iov_base = (void *)0xF000000;
520 : 4 : task.scsi.iovs = &task.scsi.iov;
521 : 4 : task.scsi.iovcnt = 1;
522 : 4 : task.scsi.length = 512;
523 : 4 : task.scsi.transfer_len = 512;
524 : 4 : task.bytes_completed = 512;
525 : :
526 : 4 : task.scsi.sense_data_len = 18;
527 : 4 : task.scsi.data_transferred = 18;
528 : 4 : task.scsi.status = SPDK_SCSI_STATUS_GOOD;
529 : :
530 : 4 : iscsi_task_response(&conn, &task);
531 : 4 : iscsi_put_pdu(pdu1);
532 : :
533 : : /*
534 : : * In this case, a SCSI Data-In PDU and a SCSI Response PDU are returned.
535 : : * Sense data are set both in payload and sense area.
536 : : * The SCSI Data-In PDU sets FINAL and the SCSI Response PDU sets UNDERFLOW.
537 : : *
538 : : * Probably there will be different implementation but keeping current SPDK
539 : : * implementation by adding UT will be valuable for any implementation.
540 : : */
541 : 4 : to_be32(&residual_count, 494);
542 : :
543 : 4 : pdu1 = TAILQ_FIRST(&g_write_pdu_list);
544 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
545 : :
546 : 4 : CU_ASSERT(pdu1->bhs.opcode == ISCSI_OP_SCSI_DATAIN);
547 : :
548 : 4 : datah = (struct iscsi_bhs_data_in *)&pdu1->bhs;
549 : :
550 : 4 : CU_ASSERT(datah->flags == ISCSI_FLAG_FINAL);
551 : :
552 : 4 : data_segment_len = DGET24(datah->data_segment_len);
553 : 4 : CU_ASSERT(data_segment_len == 18);
554 : 4 : CU_ASSERT(datah->res_cnt == 0);
555 : :
556 [ + - ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, pdu1, tailq);
557 : 4 : iscsi_put_pdu(pdu1);
558 : :
559 : 4 : pdu2 = TAILQ_FIRST(&g_write_pdu_list);
560 : : /* inform scan-build (clang 6) that these pointers are not the same */
561 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu1 != pdu2);
562 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
563 : :
564 : 4 : CU_ASSERT(pdu2->bhs.opcode == ISCSI_OP_SCSI_RSP);
565 : :
566 : 4 : resph = (struct iscsi_bhs_scsi_resp *)&pdu2->bhs;
567 : :
568 : 4 : CU_ASSERT(resph->flags == (ISCSI_SCSI_UNDERFLOW | 0x80));
569 : :
570 : 4 : data_segment_len = DGET24(resph->data_segment_len);
571 : 4 : CU_ASSERT(data_segment_len == task.scsi.sense_data_len + 2);
572 : 4 : CU_ASSERT(resph->res_cnt == residual_count);
573 : :
574 [ - + ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, pdu2, tailq);
575 : 4 : iscsi_put_pdu(pdu2);
576 : :
577 : 4 : CU_ASSERT(TAILQ_EMPTY(&g_write_pdu_list));
578 : 4 : }
579 : :
580 : : static void
581 : 4 : underflow_for_check_condition_test(void)
582 : : {
583 : 4 : struct spdk_iscsi_sess sess = {};
584 : 4 : struct spdk_iscsi_conn conn = {};
585 : 4 : struct spdk_iscsi_task task = {};
586 : 4 : struct spdk_scsi_dev dev = {};
587 : 4 : struct spdk_scsi_lun lun = {};
588 : : struct spdk_iscsi_pdu *pdu;
589 : : struct iscsi_bhs_scsi_req *scsi_req;
590 : : struct iscsi_bhs_scsi_resp *resph;
591 : : uint32_t data_segment_len;
592 : :
593 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH;
594 : :
595 : 4 : conn.sess = &sess;
596 : 4 : conn.MaxRecvDataSegmentLength = 8192;
597 : :
598 : 4 : TAILQ_INIT(&dev.luns);
599 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
600 : 4 : conn.dev = &dev;
601 : :
602 : 4 : pdu = iscsi_get_pdu(&conn);
603 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
604 : :
605 : 4 : scsi_req = (struct iscsi_bhs_scsi_req *)&pdu->bhs;
606 : 4 : scsi_req->read_bit = 1;
607 : :
608 : 4 : iscsi_task_set_pdu(&task, pdu);
609 : 4 : task.parent = NULL;
610 : :
611 : 4 : task.scsi.iov.iov_base = (void *)0xF0000000;
612 : 4 : task.scsi.iovs = &task.scsi.iov;
613 : 4 : task.scsi.iovcnt = 1;
614 : 4 : task.scsi.length = 512;
615 : 4 : task.scsi.transfer_len = 512;
616 : 4 : task.bytes_completed = 512;
617 : :
618 : 4 : task.scsi.sense_data_len = 18;
619 : 4 : task.scsi.data_transferred = 18;
620 : 4 : task.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
621 : :
622 : 4 : iscsi_task_response(&conn, &task);
623 : 4 : iscsi_put_pdu(pdu);
624 : :
625 : : /*
626 : : * In this case, a SCSI Response PDU is returned.
627 : : * Sense data is set in sense area.
628 : : * Underflow is not set.
629 : : */
630 : 4 : pdu = TAILQ_FIRST(&g_write_pdu_list);
631 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
632 : :
633 : 4 : CU_ASSERT(pdu->bhs.opcode == ISCSI_OP_SCSI_RSP);
634 : :
635 : 4 : resph = (struct iscsi_bhs_scsi_resp *)&pdu->bhs;
636 : :
637 : 4 : CU_ASSERT(resph->flags == 0x80);
638 : :
639 : 4 : data_segment_len = DGET24(resph->data_segment_len);
640 : 4 : CU_ASSERT(data_segment_len == task.scsi.sense_data_len + 2);
641 : 4 : CU_ASSERT(resph->res_cnt == 0);
642 : :
643 [ - + ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq);
644 : 4 : iscsi_put_pdu(pdu);
645 : :
646 : 4 : CU_ASSERT(TAILQ_EMPTY(&g_write_pdu_list));
647 : 4 : }
648 : :
649 : : static void
650 : 4 : add_transfer_task_test(void)
651 : : {
652 : 4 : struct spdk_iscsi_sess sess = {};
653 : 4 : struct spdk_iscsi_conn conn = {};
654 : 4 : struct spdk_iscsi_task task = {};
655 : : struct spdk_iscsi_pdu *pdu, *tmp;
656 : : struct iscsi_bhs_r2t *r2th;
657 : 4 : int rc, count = 0;
658 : : uint32_t buffer_offset, desired_xfer_len;
659 : :
660 : 4 : g_iscsi.MaxR2TPerConnection = DEFAULT_MAXR2T;
661 : :
662 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH; /* 1M */
663 : 4 : sess.MaxOutstandingR2T = DEFAULT_MAXR2T; /* 4 */
664 : :
665 : 4 : conn.sess = &sess;
666 : 4 : TAILQ_INIT(&conn.queued_r2t_tasks);
667 : 4 : TAILQ_INIT(&conn.active_r2t_tasks);
668 : :
669 : 4 : pdu = iscsi_get_pdu(&conn);
670 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu != NULL);
671 : :
672 : 4 : pdu->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH; /* 64K */
673 : 4 : task.scsi.transfer_len = 16 * 1024 * 1024;
674 : 4 : iscsi_task_set_pdu(&task, pdu);
675 : :
676 : : /* The following tests if the task is queued because R2T tasks are full. */
677 : 4 : conn.pending_r2t = DEFAULT_MAXR2T;
678 : :
679 : 4 : rc = add_transfer_task(&conn, &task);
680 : :
681 : 4 : CU_ASSERT(rc == 0);
682 : 4 : CU_ASSERT(TAILQ_FIRST(&conn.queued_r2t_tasks) == &task);
683 : :
684 [ - + ]: 4 : TAILQ_REMOVE(&conn.queued_r2t_tasks, &task, link);
685 : 4 : CU_ASSERT(TAILQ_EMPTY(&conn.queued_r2t_tasks));
686 : :
687 : : /* The following tests if multiple R2Ts are issued. */
688 : 4 : conn.pending_r2t = 0;
689 : :
690 : 4 : rc = add_transfer_task(&conn, &task);
691 : :
692 : 4 : CU_ASSERT(rc == 0);
693 : 4 : CU_ASSERT(TAILQ_FIRST(&conn.active_r2t_tasks) == &task);
694 : :
695 [ - + ]: 4 : TAILQ_REMOVE(&conn.active_r2t_tasks, &task, link);
696 : 4 : CU_ASSERT(TAILQ_EMPTY(&conn.active_r2t_tasks));
697 : :
698 : 4 : CU_ASSERT(conn.data_out_cnt == 255);
699 : 4 : CU_ASSERT(conn.pending_r2t == 1);
700 : 4 : CU_ASSERT(conn.ttt == 1);
701 : :
702 : 4 : CU_ASSERT(task.data_out_cnt == 255);
703 : 4 : CU_ASSERT(task.ttt == 1);
704 : 4 : CU_ASSERT(task.outstanding_r2t == sess.MaxOutstandingR2T);
705 : 4 : CU_ASSERT(task.next_r2t_offset ==
706 : : pdu->data_segment_len + sess.MaxBurstLength * sess.MaxOutstandingR2T);
707 : :
708 : :
709 [ + + ]: 20 : while (!TAILQ_EMPTY(&g_write_pdu_list)) {
710 : 16 : tmp = TAILQ_FIRST(&g_write_pdu_list);
711 [ + + ]: 16 : TAILQ_REMOVE(&g_write_pdu_list, tmp, tailq);
712 : :
713 : 16 : r2th = (struct iscsi_bhs_r2t *)&tmp->bhs;
714 : :
715 : 16 : buffer_offset = from_be32(&r2th->buffer_offset);
716 : 16 : CU_ASSERT(buffer_offset == pdu->data_segment_len + sess.MaxBurstLength * count);
717 : :
718 : 16 : desired_xfer_len = from_be32(&r2th->desired_xfer_len);
719 : 16 : CU_ASSERT(desired_xfer_len == sess.MaxBurstLength);
720 : :
721 : 16 : iscsi_put_pdu(tmp);
722 : 16 : count++;
723 : : }
724 : :
725 : 4 : CU_ASSERT(count == DEFAULT_MAXR2T);
726 : :
727 : 4 : iscsi_put_pdu(pdu);
728 : 4 : }
729 : :
730 : : static void
731 : 4 : get_transfer_task_test(void)
732 : : {
733 : 4 : struct spdk_iscsi_sess sess = {};
734 : 4 : struct spdk_iscsi_conn conn = {};
735 : 4 : struct spdk_iscsi_task task1 = {}, task2 = {}, *task;
736 : : struct spdk_iscsi_pdu *pdu1, *pdu2, *pdu;
737 : : int rc;
738 : :
739 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
740 : 4 : sess.MaxOutstandingR2T = 1;
741 : :
742 : 4 : conn.sess = &sess;
743 : 4 : TAILQ_INIT(&conn.active_r2t_tasks);
744 : :
745 : 4 : pdu1 = iscsi_get_pdu(&conn);
746 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
747 : :
748 : 4 : pdu1->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
749 : 4 : task1.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
750 : 4 : iscsi_task_set_pdu(&task1, pdu1);
751 : :
752 : 4 : rc = add_transfer_task(&conn, &task1);
753 : 4 : CU_ASSERT(rc == 0);
754 : :
755 : 4 : pdu2 = iscsi_get_pdu(&conn);
756 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
757 : :
758 : 4 : pdu2->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
759 : 4 : task2.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
760 : 4 : iscsi_task_set_pdu(&task2, pdu2);
761 : :
762 : 4 : rc = add_transfer_task(&conn, &task2);
763 : 4 : CU_ASSERT(rc == 0);
764 : :
765 : 4 : task = get_transfer_task(&conn, 1);
766 : 4 : CU_ASSERT(task == &task1);
767 : :
768 : 4 : task = get_transfer_task(&conn, 2);
769 : 4 : CU_ASSERT(task == &task2);
770 : :
771 [ + + ]: 12 : while (!TAILQ_EMPTY(&conn.active_r2t_tasks)) {
772 : 8 : task = TAILQ_FIRST(&conn.active_r2t_tasks);
773 [ + + ]: 8 : TAILQ_REMOVE(&conn.active_r2t_tasks, task, link);
774 : : }
775 : :
776 [ - + ]: 4 : while (!TAILQ_EMPTY(&g_write_pdu_list)) {
777 : 0 : pdu = TAILQ_FIRST(&g_write_pdu_list);
778 [ # # ]: 0 : TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq);
779 : 0 : iscsi_put_pdu(pdu);
780 : : }
781 : :
782 : 4 : iscsi_put_pdu(pdu2);
783 : 4 : iscsi_put_pdu(pdu1);
784 : 4 : }
785 : :
786 : : static void
787 : 4 : del_transfer_task_test(void)
788 : : {
789 : 4 : struct spdk_iscsi_sess sess = {};
790 : 4 : struct spdk_iscsi_conn conn = {};
791 : : struct spdk_iscsi_task *task1, *task2, *task3, *task4, *task5;
792 : : struct spdk_iscsi_pdu *pdu1, *pdu2, *pdu3, *pdu4, *pdu5, *pdu;
793 : : int rc;
794 : :
795 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
796 : 4 : sess.MaxOutstandingR2T = 1;
797 : :
798 : 4 : conn.sess = &sess;
799 : 4 : TAILQ_INIT(&conn.active_r2t_tasks);
800 : 4 : TAILQ_INIT(&conn.queued_r2t_tasks);
801 : :
802 : 4 : pdu1 = iscsi_get_pdu(&conn);
803 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
804 : :
805 : 4 : pdu1->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
806 : :
807 : 4 : task1 = iscsi_task_get(&conn, NULL, NULL);
808 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task1 != NULL);
809 : :
810 : 4 : task1->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
811 : 4 : iscsi_task_set_pdu(task1, pdu1);
812 : 4 : task1->tag = 11;
813 : :
814 : 4 : rc = add_transfer_task(&conn, task1);
815 : 4 : CU_ASSERT(rc == 0);
816 : :
817 : 4 : pdu2 = iscsi_get_pdu(&conn);
818 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
819 : :
820 : 4 : pdu2->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
821 : :
822 : 4 : task2 = iscsi_task_get(&conn, NULL, NULL);
823 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task2 != NULL);
824 : :
825 : 4 : task2->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
826 : 4 : iscsi_task_set_pdu(task2, pdu2);
827 : 4 : task2->tag = 12;
828 : :
829 : 4 : rc = add_transfer_task(&conn, task2);
830 : 4 : CU_ASSERT(rc == 0);
831 : :
832 : 4 : pdu3 = iscsi_get_pdu(&conn);
833 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu3 != NULL);
834 : :
835 : 4 : pdu3->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
836 : :
837 : 4 : task3 = iscsi_task_get(&conn, NULL, NULL);
838 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task3 != NULL);
839 : :
840 : 4 : task3->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
841 : 4 : iscsi_task_set_pdu(task3, pdu3);
842 : 4 : task3->tag = 13;
843 : :
844 : 4 : rc = add_transfer_task(&conn, task3);
845 : 4 : CU_ASSERT(rc == 0);
846 : :
847 : 4 : pdu4 = iscsi_get_pdu(&conn);
848 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu4 != NULL);
849 : :
850 : 4 : pdu4->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
851 : :
852 : 4 : task4 = iscsi_task_get(&conn, NULL, NULL);
853 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task4 != NULL);
854 : :
855 : 4 : task4->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
856 : 4 : iscsi_task_set_pdu(task4, pdu4);
857 : 4 : task4->tag = 14;
858 : :
859 : 4 : rc = add_transfer_task(&conn, task4);
860 : 4 : CU_ASSERT(rc == 0);
861 : :
862 : 4 : pdu5 = iscsi_get_pdu(&conn);
863 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu5 != NULL);
864 : :
865 : 4 : pdu5->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
866 : :
867 : 4 : task5 = iscsi_task_get(&conn, NULL, NULL);
868 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(task5 != NULL);
869 : :
870 : 4 : task5->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
871 : 4 : iscsi_task_set_pdu(task5, pdu5);
872 : 4 : task5->tag = 15;
873 : :
874 : 4 : rc = add_transfer_task(&conn, task5);
875 : 4 : CU_ASSERT(rc == 0);
876 : :
877 : 4 : CU_ASSERT(get_transfer_task(&conn, 1) == task1);
878 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
879 : 4 : iscsi_del_transfer_task(&conn, 11);
880 : 4 : CU_ASSERT(get_transfer_task(&conn, 1) == NULL);
881 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == task5);
882 : :
883 : 4 : CU_ASSERT(get_transfer_task(&conn, 2) == task2);
884 : 4 : iscsi_del_transfer_task(&conn, 12);
885 : 4 : CU_ASSERT(get_transfer_task(&conn, 2) == NULL);
886 : :
887 : 4 : CU_ASSERT(get_transfer_task(&conn, 3) == task3);
888 : 4 : iscsi_del_transfer_task(&conn, 13);
889 : 4 : CU_ASSERT(get_transfer_task(&conn, 3) == NULL);
890 : :
891 : 4 : CU_ASSERT(get_transfer_task(&conn, 4) == task4);
892 : 4 : iscsi_del_transfer_task(&conn, 14);
893 : 4 : CU_ASSERT(get_transfer_task(&conn, 4) == NULL);
894 : :
895 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == task5);
896 : 4 : iscsi_del_transfer_task(&conn, 15);
897 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
898 : :
899 : 4 : CU_ASSERT(TAILQ_EMPTY(&conn.active_r2t_tasks));
900 : :
901 [ - + ]: 4 : while (!TAILQ_EMPTY(&g_write_pdu_list)) {
902 : 0 : pdu = TAILQ_FIRST(&g_write_pdu_list);
903 [ # # ]: 0 : TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq);
904 : 0 : iscsi_put_pdu(pdu);
905 : : }
906 : :
907 : 4 : iscsi_put_pdu(pdu5);
908 : 4 : iscsi_put_pdu(pdu4);
909 : 4 : iscsi_put_pdu(pdu3);
910 : 4 : iscsi_put_pdu(pdu2);
911 : 4 : iscsi_put_pdu(pdu1);
912 : 4 : }
913 : :
914 : : static void
915 : 4 : clear_all_transfer_tasks_test(void)
916 : : {
917 : 4 : struct spdk_iscsi_sess sess = {};
918 : 4 : struct spdk_iscsi_conn conn = {};
919 : : struct spdk_iscsi_task *task1, *task2, *task3, *task4, *task5, *task6;
920 : : struct spdk_iscsi_pdu *pdu1, *pdu2, *pdu3, *pdu4, *pdu5, *pdu6, *pdu;
921 : : struct spdk_iscsi_pdu *mgmt_pdu1, *mgmt_pdu2;
922 : 4 : struct spdk_scsi_lun lun1 = {}, lun2 = {};
923 : : uint32_t alloc_cmd_sn;
924 : : int rc;
925 : :
926 : 4 : sess.MaxBurstLength = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
927 : 4 : sess.MaxOutstandingR2T = 1;
928 : :
929 : 4 : conn.sess = &sess;
930 : 4 : TAILQ_INIT(&conn.active_r2t_tasks);
931 : 4 : TAILQ_INIT(&conn.queued_r2t_tasks);
932 : :
933 : 4 : alloc_cmd_sn = 10;
934 : :
935 : 4 : task1 = iscsi_task_get(&conn, NULL, NULL);
936 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task1 != NULL);
937 : 4 : pdu1 = iscsi_get_pdu(&conn);
938 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
939 : :
940 : 4 : pdu1->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
941 : 4 : pdu1->cmd_sn = alloc_cmd_sn;
942 : 4 : alloc_cmd_sn++;
943 : 4 : task1->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
944 : 4 : task1->scsi.lun = &lun1;
945 : 4 : iscsi_task_set_pdu(task1, pdu1);
946 : :
947 : 4 : rc = add_transfer_task(&conn, task1);
948 : 4 : CU_ASSERT(rc == 0);
949 : :
950 : 4 : mgmt_pdu1 = iscsi_get_pdu(&conn);
951 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(mgmt_pdu1 != NULL);
952 : :
953 : 4 : mgmt_pdu1->cmd_sn = alloc_cmd_sn;
954 : 4 : alloc_cmd_sn++;
955 : :
956 : 4 : task2 = iscsi_task_get(&conn, NULL, NULL);
957 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task2 != NULL);
958 : 4 : pdu2 = iscsi_get_pdu(&conn);
959 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
960 : :
961 : 4 : pdu2->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
962 : 4 : pdu2->cmd_sn = alloc_cmd_sn;
963 : 4 : alloc_cmd_sn++;
964 : 4 : task2->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
965 : 4 : task2->scsi.lun = &lun1;
966 : 4 : iscsi_task_set_pdu(task2, pdu2);
967 : :
968 : 4 : rc = add_transfer_task(&conn, task2);
969 : 4 : CU_ASSERT(rc == 0);
970 : :
971 : 4 : task3 = iscsi_task_get(&conn, NULL, NULL);
972 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task3 != NULL);
973 : 4 : pdu3 = iscsi_get_pdu(&conn);
974 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu3 != NULL);
975 : :
976 : 4 : pdu3->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
977 : 4 : pdu3->cmd_sn = alloc_cmd_sn;
978 : 4 : alloc_cmd_sn++;
979 : 4 : task3->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
980 : 4 : task3->scsi.lun = &lun1;
981 : 4 : iscsi_task_set_pdu(task3, pdu3);
982 : :
983 : 4 : rc = add_transfer_task(&conn, task3);
984 : 4 : CU_ASSERT(rc == 0);
985 : :
986 : 4 : task4 = iscsi_task_get(&conn, NULL, NULL);
987 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task4 != NULL);
988 : 4 : pdu4 = iscsi_get_pdu(&conn);
989 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu4 != NULL);
990 : :
991 : 4 : pdu4->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
992 : 4 : pdu4->cmd_sn = alloc_cmd_sn;
993 : 4 : alloc_cmd_sn++;
994 : 4 : task4->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
995 : 4 : task4->scsi.lun = &lun2;
996 : 4 : iscsi_task_set_pdu(task4, pdu4);
997 : :
998 : 4 : rc = add_transfer_task(&conn, task4);
999 : 4 : CU_ASSERT(rc == 0);
1000 : :
1001 : 4 : task5 = iscsi_task_get(&conn, NULL, NULL);
1002 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task5 != NULL);
1003 : 4 : pdu5 = iscsi_get_pdu(&conn);
1004 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu5 != NULL);
1005 : :
1006 : 4 : pdu5->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1007 : 4 : pdu5->cmd_sn = alloc_cmd_sn;
1008 : 4 : alloc_cmd_sn++;
1009 : 4 : task5->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1010 : 4 : task5->scsi.lun = &lun2;
1011 : 4 : iscsi_task_set_pdu(task5, pdu5);
1012 : :
1013 : 4 : rc = add_transfer_task(&conn, task5);
1014 : 4 : CU_ASSERT(rc == 0);
1015 : :
1016 : 4 : mgmt_pdu2 = iscsi_get_pdu(&conn);
1017 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(mgmt_pdu2 != NULL);
1018 : :
1019 : 4 : mgmt_pdu2->cmd_sn = alloc_cmd_sn;
1020 : 4 : alloc_cmd_sn++;
1021 : :
1022 : 4 : task6 = iscsi_task_get(&conn, NULL, NULL);
1023 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(task6 != NULL);
1024 : 4 : pdu6 = iscsi_get_pdu(&conn);
1025 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(pdu6 != NULL);
1026 : :
1027 : 4 : pdu6->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1028 : 4 : pdu6->cmd_sn = alloc_cmd_sn;
1029 : 4 : alloc_cmd_sn++;
1030 : 4 : task5->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1031 : 4 : task6->scsi.lun = &lun2;
1032 : 4 : iscsi_task_set_pdu(task6, pdu6);
1033 : :
1034 : 4 : rc = add_transfer_task(&conn, task6);
1035 : 4 : CU_ASSERT(rc == 0);
1036 : :
1037 : 4 : CU_ASSERT(conn.ttt == 4);
1038 : :
1039 : 4 : CU_ASSERT(get_transfer_task(&conn, 1) == task1);
1040 : 4 : CU_ASSERT(get_transfer_task(&conn, 2) == task2);
1041 : 4 : CU_ASSERT(get_transfer_task(&conn, 3) == task3);
1042 : 4 : CU_ASSERT(get_transfer_task(&conn, 4) == task4);
1043 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
1044 : :
1045 : 4 : iscsi_clear_all_transfer_task(&conn, &lun1, mgmt_pdu1);
1046 : :
1047 : 4 : CU_ASSERT(!TAILQ_EMPTY(&conn.queued_r2t_tasks));
1048 : 4 : CU_ASSERT(get_transfer_task(&conn, 1) == NULL);
1049 : 4 : CU_ASSERT(get_transfer_task(&conn, 2) == task2);
1050 : 4 : CU_ASSERT(get_transfer_task(&conn, 3) == task3);
1051 : 4 : CU_ASSERT(get_transfer_task(&conn, 4) == task4);
1052 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == task5);
1053 : 4 : CU_ASSERT(get_transfer_task(&conn, 6) == NULL);
1054 : :
1055 : 4 : iscsi_clear_all_transfer_task(&conn, &lun1, NULL);
1056 : :
1057 : 4 : CU_ASSERT(TAILQ_EMPTY(&conn.queued_r2t_tasks));
1058 : 4 : CU_ASSERT(get_transfer_task(&conn, 1) == NULL);
1059 : 4 : CU_ASSERT(get_transfer_task(&conn, 2) == NULL);
1060 : 4 : CU_ASSERT(get_transfer_task(&conn, 3) == NULL);
1061 : 4 : CU_ASSERT(get_transfer_task(&conn, 4) == task4);
1062 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == task5);
1063 : 4 : CU_ASSERT(get_transfer_task(&conn, 6) == task6);
1064 : :
1065 : 4 : iscsi_clear_all_transfer_task(&conn, &lun2, mgmt_pdu2);
1066 : :
1067 : 4 : CU_ASSERT(get_transfer_task(&conn, 4) == NULL);
1068 : 4 : CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
1069 : 4 : CU_ASSERT(get_transfer_task(&conn, 6) == task6);
1070 : :
1071 : 4 : iscsi_clear_all_transfer_task(&conn, NULL, NULL);
1072 : :
1073 : 4 : CU_ASSERT(get_transfer_task(&conn, 6) == NULL);
1074 : :
1075 : 4 : CU_ASSERT(TAILQ_EMPTY(&conn.active_r2t_tasks));
1076 [ + + ]: 28 : while (!TAILQ_EMPTY(&g_write_pdu_list)) {
1077 : 24 : pdu = TAILQ_FIRST(&g_write_pdu_list);
1078 [ + + ]: 24 : TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq);
1079 : 24 : iscsi_put_pdu(pdu);
1080 : : }
1081 : :
1082 : 4 : iscsi_put_pdu(mgmt_pdu2);
1083 : 4 : iscsi_put_pdu(mgmt_pdu1);
1084 : 4 : iscsi_put_pdu(pdu6);
1085 : 4 : iscsi_put_pdu(pdu5);
1086 : 4 : iscsi_put_pdu(pdu4);
1087 : 4 : iscsi_put_pdu(pdu3);
1088 : 4 : iscsi_put_pdu(pdu2);
1089 : 4 : iscsi_put_pdu(pdu1);
1090 : 4 : }
1091 : :
1092 : : static void
1093 : 4 : build_iovs_test(void)
1094 : : {
1095 : 4 : struct spdk_iscsi_conn conn = {};
1096 : 4 : struct spdk_iscsi_pdu pdu = {};
1097 : 4 : struct iovec iovs[5] = {};
1098 : : uint8_t *data;
1099 : 4 : uint32_t mapped_length = 0;
1100 : : int rc;
1101 : :
1102 : 4 : conn.header_digest = true;
1103 : 4 : conn.data_digest = true;
1104 : :
1105 : 4 : DSET24(&pdu.bhs.data_segment_len, 512);
1106 : 4 : data = calloc(1, 512);
1107 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(data != NULL);
1108 : 4 : pdu.data = data;
1109 : :
1110 : 4 : pdu.bhs.total_ahs_len = 0;
1111 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI;
1112 : :
1113 : 4 : pdu.writev_offset = 0;
1114 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1115 : 4 : CU_ASSERT(rc == 4);
1116 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1117 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1118 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1119 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1120 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
1121 : 4 : CU_ASSERT(iovs[2].iov_len == 512);
1122 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)pdu.data_digest);
1123 : 4 : CU_ASSERT(iovs[3].iov_len == ISCSI_DIGEST_LEN);
1124 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN);
1125 : :
1126 : 4 : pdu.writev_offset = ISCSI_BHS_LEN / 2;
1127 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1128 : 4 : CU_ASSERT(rc == 4);
1129 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)((uint8_t *)&pdu.bhs + ISCSI_BHS_LEN / 2));
1130 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN / 2);
1131 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1132 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1133 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
1134 : 4 : CU_ASSERT(iovs[2].iov_len == 512);
1135 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)pdu.data_digest);
1136 : 4 : CU_ASSERT(iovs[3].iov_len == ISCSI_DIGEST_LEN);
1137 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN / 2 + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN);
1138 : :
1139 : 4 : pdu.writev_offset = ISCSI_BHS_LEN;
1140 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1141 : 4 : CU_ASSERT(rc == 3);
1142 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)pdu.header_digest);
1143 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN);
1144 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.data);
1145 : 4 : CU_ASSERT(iovs[1].iov_len == 512);
1146 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data_digest);
1147 : 4 : CU_ASSERT(iovs[2].iov_len == ISCSI_DIGEST_LEN);
1148 : 4 : CU_ASSERT(mapped_length == ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN);
1149 : :
1150 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN / 2;
1151 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1152 : 4 : CU_ASSERT(rc == 3);
1153 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)((uint8_t *)pdu.header_digest + ISCSI_DIGEST_LEN / 2));
1154 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN / 2);
1155 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.data);
1156 : 4 : CU_ASSERT(iovs[1].iov_len == 512);
1157 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data_digest);
1158 : 4 : CU_ASSERT(iovs[2].iov_len == ISCSI_DIGEST_LEN);
1159 : 4 : CU_ASSERT(mapped_length == ISCSI_DIGEST_LEN / 2 + 512 + ISCSI_DIGEST_LEN);
1160 : :
1161 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN;
1162 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1163 : 4 : CU_ASSERT(rc == 2);
1164 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)pdu.data);
1165 : 4 : CU_ASSERT(iovs[0].iov_len == 512);
1166 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.data_digest);
1167 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1168 : 4 : CU_ASSERT(mapped_length == 512 + ISCSI_DIGEST_LEN);
1169 : :
1170 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512;
1171 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1172 : 4 : CU_ASSERT(rc == 1);
1173 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)pdu.data_digest);
1174 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN);
1175 : 4 : CU_ASSERT(mapped_length == ISCSI_DIGEST_LEN);
1176 : :
1177 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN / 2;
1178 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1179 : 4 : CU_ASSERT(rc == 1);
1180 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)((uint8_t *)pdu.data_digest + ISCSI_DIGEST_LEN / 2));
1181 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN / 2);
1182 : 4 : CU_ASSERT(mapped_length == ISCSI_DIGEST_LEN / 2);
1183 : :
1184 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN;
1185 : 4 : rc = iscsi_build_iovs(&conn, iovs, 5, &pdu, &mapped_length);
1186 : 4 : CU_ASSERT(rc == 0);
1187 : 4 : CU_ASSERT(mapped_length == 0);
1188 : :
1189 : 4 : pdu.writev_offset = 0;
1190 : 4 : rc = iscsi_build_iovs(&conn, iovs, 1, &pdu, &mapped_length);
1191 : 4 : CU_ASSERT(rc == 1);
1192 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1193 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1194 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN);
1195 : :
1196 : 4 : rc = iscsi_build_iovs(&conn, iovs, 2, &pdu, &mapped_length);
1197 : 4 : CU_ASSERT(rc == 2);
1198 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1199 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1200 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1201 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1202 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN + ISCSI_DIGEST_LEN);
1203 : :
1204 : 4 : rc = iscsi_build_iovs(&conn, iovs, 3, &pdu, &mapped_length);
1205 : 4 : CU_ASSERT(rc == 3);
1206 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1207 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1208 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1209 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1210 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
1211 : 4 : CU_ASSERT(iovs[2].iov_len == 512);
1212 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512);
1213 : :
1214 : 4 : rc = iscsi_build_iovs(&conn, iovs, 4, &pdu, &mapped_length);
1215 : 4 : CU_ASSERT(rc == 4);
1216 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1217 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1218 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1219 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1220 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
1221 : 4 : CU_ASSERT(iovs[2].iov_len == 512);
1222 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)pdu.data_digest);
1223 : 4 : CU_ASSERT(iovs[3].iov_len == ISCSI_DIGEST_LEN);
1224 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 512 + ISCSI_DIGEST_LEN);
1225 : :
1226 : 4 : free(data);
1227 : 4 : }
1228 : :
1229 : : static void
1230 : 4 : build_iovs_with_md_test(void)
1231 : : {
1232 : 4 : struct spdk_iscsi_conn conn = {};
1233 : 4 : struct spdk_iscsi_pdu pdu = {};
1234 : 4 : struct iovec iovs[6] = {};
1235 : : uint8_t *data;
1236 : 4 : uint32_t mapped_length = 0;
1237 : : int rc;
1238 : 3 : struct spdk_dif_ctx_init_ext_opts dif_opts;
1239 : :
1240 : 4 : conn.header_digest = true;
1241 : 4 : conn.data_digest = true;
1242 : :
1243 : 4 : DSET24(&pdu.bhs.data_segment_len, 4096 * 2);
1244 : 4 : data = calloc(1, (4096 + 128) * 2);
1245 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(data != NULL);
1246 : 4 : pdu.data = data;
1247 : 4 : pdu.data_buf_len = (4096 + 128) * 2;
1248 : :
1249 : 4 : pdu.bhs.total_ahs_len = 0;
1250 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI;
1251 : :
1252 : 4 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
1253 : 4 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
1254 : 4 : rc = spdk_dif_ctx_init(&pdu.dif_ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
1255 : : 0, 0, 0, 0, 0, 0, &dif_opts);
1256 : 4 : CU_ASSERT(rc == 0);
1257 : :
1258 : 4 : pdu.dif_insert_or_strip = true;
1259 : :
1260 : 4 : pdu.writev_offset = 0;
1261 : 4 : rc = iscsi_build_iovs(&conn, iovs, 6, &pdu, &mapped_length);
1262 : 4 : CU_ASSERT(rc == 5);
1263 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1264 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1265 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1266 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1267 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
1268 : 4 : CU_ASSERT(iovs[2].iov_len == 4096);
1269 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)(pdu.data + 4096 + 128));
1270 : 4 : CU_ASSERT(iovs[3].iov_len == 4096);
1271 : 4 : CU_ASSERT(iovs[4].iov_base == (void *)pdu.data_digest);
1272 : 4 : CU_ASSERT(iovs[4].iov_len == ISCSI_DIGEST_LEN);
1273 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 4096 * 2 + ISCSI_DIGEST_LEN);
1274 : :
1275 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 2048;
1276 : 4 : rc = iscsi_build_iovs(&conn, iovs, 6, &pdu, &mapped_length);
1277 : 4 : CU_ASSERT(rc == 3);
1278 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)(pdu.data + 2048));
1279 : 4 : CU_ASSERT(iovs[0].iov_len == 2048);
1280 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)(pdu.data + 4096 + 128));
1281 : 4 : CU_ASSERT(iovs[1].iov_len == 4096);
1282 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data_digest);
1283 : 4 : CU_ASSERT(iovs[2].iov_len == ISCSI_DIGEST_LEN);
1284 : 4 : CU_ASSERT(mapped_length == 2048 + 4096 + ISCSI_DIGEST_LEN);
1285 : :
1286 : 4 : pdu.writev_offset = ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 4096 * 2;
1287 : 4 : rc = iscsi_build_iovs(&conn, iovs, 6, &pdu, &mapped_length);
1288 : 4 : CU_ASSERT(rc == 1);
1289 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)pdu.data_digest);
1290 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_DIGEST_LEN);
1291 : 4 : CU_ASSERT(mapped_length == ISCSI_DIGEST_LEN);
1292 : :
1293 : 4 : pdu.writev_offset = 0;
1294 : 4 : rc = iscsi_build_iovs(&conn, iovs, 3, &pdu, &mapped_length);
1295 : 4 : CU_ASSERT(rc == 3);
1296 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.bhs);
1297 : 4 : CU_ASSERT(iovs[0].iov_len == ISCSI_BHS_LEN);
1298 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)pdu.header_digest);
1299 : 4 : CU_ASSERT(iovs[1].iov_len == ISCSI_DIGEST_LEN);
1300 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)pdu.data);
1301 : 4 : CU_ASSERT(iovs[2].iov_len == 4096);
1302 : 4 : CU_ASSERT(mapped_length == ISCSI_BHS_LEN + ISCSI_DIGEST_LEN + 4096);
1303 : :
1304 : 4 : free(data);
1305 : 4 : }
1306 : :
1307 : : static void
1308 : 56 : check_iscsi_reject(struct spdk_iscsi_pdu *pdu, uint8_t reason)
1309 : : {
1310 : : struct spdk_iscsi_pdu *rsp_pdu;
1311 : : struct iscsi_bhs_reject *reject_bhs;
1312 : :
1313 [ - + ]: 56 : CU_ASSERT(pdu->is_rejected == true);
1314 : 56 : rsp_pdu = TAILQ_FIRST(&g_write_pdu_list);
1315 : 56 : CU_ASSERT(rsp_pdu != NULL);
1316 : 56 : reject_bhs = (struct iscsi_bhs_reject *)&rsp_pdu->bhs;
1317 : 56 : CU_ASSERT(reject_bhs->reason == reason);
1318 : :
1319 [ + + ]: 56 : TAILQ_REMOVE(&g_write_pdu_list, rsp_pdu, tailq);
1320 : 56 : iscsi_put_pdu(rsp_pdu);
1321 : 56 : pdu->is_rejected = false;
1322 : 56 : }
1323 : :
1324 : : static void
1325 : 12 : check_login_response(uint8_t status_class, uint8_t status_detail)
1326 : : {
1327 : : struct spdk_iscsi_pdu *rsp_pdu;
1328 : : struct iscsi_bhs_login_rsp *login_rsph;
1329 : :
1330 : 12 : rsp_pdu = TAILQ_FIRST(&g_write_pdu_list);
1331 : 12 : CU_ASSERT(rsp_pdu != NULL);
1332 : 12 : login_rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs;
1333 : 12 : CU_ASSERT(login_rsph->status_class == status_class);
1334 : 12 : CU_ASSERT(login_rsph->status_detail == status_detail);
1335 : :
1336 [ + + ]: 12 : TAILQ_REMOVE(&g_write_pdu_list, rsp_pdu, tailq);
1337 : 12 : iscsi_put_pdu(rsp_pdu);
1338 : 12 : }
1339 : :
1340 : : static void
1341 : 4 : pdu_hdr_op_login_test(void)
1342 : : {
1343 : 4 : struct spdk_iscsi_sess sess = {};
1344 : 4 : struct spdk_iscsi_conn conn = {};
1345 : 4 : struct spdk_iscsi_pdu pdu = {};
1346 : : struct iscsi_bhs_login_req *login_reqh;
1347 : : int rc;
1348 : :
1349 : 4 : login_reqh = (struct iscsi_bhs_login_req *)&pdu.bhs;
1350 : :
1351 : : /* Case 1 - On discovery session, target only accepts text requests with the
1352 : : * SendTargets key and logout request with reason "close the session".
1353 : : */
1354 : 4 : sess.session_type = SESSION_TYPE_DISCOVERY;
1355 : 4 : conn.full_feature = true;
1356 : 4 : conn.sess = &sess;
1357 : :
1358 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1359 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1360 : :
1361 : : /* Case 2 - Data segment length is limited to be not more than 8KB, the default
1362 : : * FirstBurstLength, for login request.
1363 : : */
1364 : 4 : sess.session_type = SESSION_TYPE_INVALID;
1365 : 4 : conn.full_feature = false;
1366 : 4 : conn.sess = NULL;
1367 : 4 : pdu.data_segment_len = SPDK_ISCSI_FIRST_BURST_LENGTH + 1;
1368 : :
1369 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1370 : 4 : CU_ASSERT(rc == 0);
1371 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1372 : :
1373 : : /* Case 3 - PDU pool is empty */
1374 : 4 : pdu.data_segment_len = SPDK_ISCSI_FIRST_BURST_LENGTH;
1375 : 4 : g_pdu_pool_is_empty = true;
1376 : :
1377 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1378 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1379 : :
1380 : : /* Case 4 - A login request with the C bit set to 1 must have the T bit set to 0. */
1381 : 4 : g_pdu_pool_is_empty = false;
1382 : 4 : login_reqh->flags |= ISCSI_LOGIN_TRANSIT;
1383 : 4 : login_reqh->flags |= ISCSI_LOGIN_CONTINUE;
1384 : :
1385 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1386 : 4 : CU_ASSERT(rc == 0);
1387 : 4 : check_login_response(ISCSI_CLASS_INITIATOR_ERROR, ISCSI_LOGIN_INITIATOR_ERROR);
1388 : :
1389 : : /* Case 5 - Both version-min and version-max must be set to 0x00. */
1390 : 4 : login_reqh->flags = 0;
1391 : 4 : login_reqh->version_min = ISCSI_VERSION + 1;
1392 : :
1393 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1394 : 4 : CU_ASSERT(rc == 0);
1395 : 4 : check_login_response(ISCSI_CLASS_INITIATOR_ERROR, ISCSI_LOGIN_UNSUPPORTED_VERSION);
1396 : :
1397 : : /* Case 6 - T bit is set to 1 correctly but invalid stage code is set to NSG. */
1398 : 4 : login_reqh->version_min = ISCSI_VERSION;
1399 : 4 : login_reqh->flags |= ISCSI_LOGIN_TRANSIT;
1400 : 4 : login_reqh->flags |= ISCSI_NSG_RESERVED_CODE;
1401 : :
1402 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1403 : 4 : CU_ASSERT(rc == 0);
1404 : 4 : check_login_response(ISCSI_CLASS_INITIATOR_ERROR, ISCSI_LOGIN_INITIATOR_ERROR);
1405 : :
1406 : : /* Case 7 - Login request is correct. Login response is initialized and set to
1407 : : * the current connection.
1408 : : */
1409 : 4 : login_reqh->flags = 0;
1410 : :
1411 : 4 : rc = iscsi_pdu_hdr_op_login(&conn, &pdu);
1412 : 4 : CU_ASSERT(rc == 0);
1413 : 4 : CU_ASSERT(conn.login_rsp_pdu != NULL);
1414 : :
1415 : 4 : iscsi_put_pdu(conn.login_rsp_pdu);
1416 : 4 : }
1417 : :
1418 : : static void
1419 : 4 : pdu_hdr_op_text_test(void)
1420 : : {
1421 : 4 : struct spdk_iscsi_sess sess = {};
1422 : 4 : struct spdk_iscsi_conn conn = {};
1423 : 4 : struct spdk_iscsi_pdu pdu = {};
1424 : : struct iscsi_bhs_text_req *text_reqh;
1425 : : int rc;
1426 : :
1427 : 4 : text_reqh = (struct iscsi_bhs_text_req *)&pdu.bhs;
1428 : :
1429 : 4 : conn.sess = &sess;
1430 : :
1431 : : /* Case 1 - Data segment length for text request must not be more than
1432 : : * FirstBurstLength plus extra space to account for digests.
1433 : : */
1434 : 4 : pdu.data_segment_len = iscsi_get_max_immediate_data_size() + 1;
1435 : :
1436 : 4 : rc = iscsi_pdu_hdr_op_text(&conn, &pdu);
1437 : 4 : CU_ASSERT(rc == 0);
1438 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1439 : :
1440 : : /* Case 2 - A text request with the C bit set to 1 must have the F bit set to 0. */
1441 : 4 : pdu.data_segment_len = iscsi_get_max_immediate_data_size();
1442 : 4 : text_reqh->flags |= ISCSI_FLAG_FINAL;
1443 : 4 : text_reqh->flags |= ISCSI_TEXT_CONTINUE;
1444 : :
1445 : 4 : rc = iscsi_pdu_hdr_op_text(&conn, &pdu);
1446 : 4 : CU_ASSERT(rc == -1);
1447 : :
1448 : : /* Case 3 - ExpStatSN of the text request is expected to match StatSN of the current
1449 : : * connection. But StarPort iSCSI initiator didn't follow the expectation. In this
1450 : : * case we overwrite StatSN by ExpStatSN and processes the request as correct.
1451 : : */
1452 : 4 : text_reqh->flags = 0;
1453 : 4 : to_be32(&text_reqh->exp_stat_sn, 1234);
1454 : 4 : to_be32(&conn.StatSN, 4321);
1455 : :
1456 : 4 : rc = iscsi_pdu_hdr_op_text(&conn, &pdu);
1457 : 4 : CU_ASSERT(rc == 0);
1458 : 4 : CU_ASSERT(conn.StatSN == 1234);
1459 : :
1460 : : /* Case 4 - Text request is the first in the sequence of text requests and responses,
1461 : : * and so its ITT is hold to the current connection.
1462 : : */
1463 : 4 : sess.current_text_itt = 0xffffffffU;
1464 : 4 : to_be32(&text_reqh->itt, 5678);
1465 : :
1466 : 4 : rc = iscsi_pdu_hdr_op_text(&conn, &pdu);
1467 : 4 : CU_ASSERT(rc == 0);
1468 : 4 : CU_ASSERT(sess.current_text_itt == 5678);
1469 : :
1470 : : /* Case 5 - If text request is sent as part of a sequence of text requests and responses,
1471 : : * its ITT must be the same for all the text requests. But it was not. */
1472 : 4 : sess.current_text_itt = 5679;
1473 : :
1474 : 4 : rc = iscsi_pdu_hdr_op_text(&conn, &pdu);
1475 : 4 : CU_ASSERT(rc == 0);
1476 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1477 : :
1478 : : /* Case 6 - Different from case 5, its ITT matches the value saved in the connection. */
1479 : 4 : text_reqh->flags = 0;
1480 : 4 : sess.current_text_itt = 5678;
1481 : :
1482 : 4 : rc = iscsi_pdu_hdr_op_text(&conn, &pdu);
1483 : 4 : CU_ASSERT(rc == 0);
1484 : 4 : }
1485 : :
1486 : : static void
1487 : 12 : check_logout_response(uint8_t response, uint32_t stat_sn, uint32_t exp_cmd_sn,
1488 : : uint32_t max_cmd_sn)
1489 : : {
1490 : : struct spdk_iscsi_pdu *rsp_pdu;
1491 : : struct iscsi_bhs_logout_resp *logout_rsph;
1492 : :
1493 : 12 : rsp_pdu = TAILQ_FIRST(&g_write_pdu_list);
1494 : 12 : CU_ASSERT(rsp_pdu != NULL);
1495 : 12 : logout_rsph = (struct iscsi_bhs_logout_resp *)&rsp_pdu->bhs;
1496 : 12 : CU_ASSERT(logout_rsph->response == response);
1497 : 12 : CU_ASSERT(from_be32(&logout_rsph->stat_sn) == stat_sn);
1498 : 12 : CU_ASSERT(from_be32(&logout_rsph->exp_cmd_sn) == exp_cmd_sn);
1499 : 12 : CU_ASSERT(from_be32(&logout_rsph->max_cmd_sn) == max_cmd_sn);
1500 : :
1501 [ + + ]: 12 : TAILQ_REMOVE(&g_write_pdu_list, rsp_pdu, tailq);
1502 : 12 : iscsi_put_pdu(rsp_pdu);
1503 : 12 : }
1504 : :
1505 : : static void
1506 : 4 : pdu_hdr_op_logout_test(void)
1507 : : {
1508 : 4 : struct spdk_iscsi_sess sess = {};
1509 : 4 : struct spdk_iscsi_conn conn = {};
1510 : 4 : struct spdk_iscsi_pdu pdu = {};
1511 : : struct iscsi_bhs_logout_req *logout_reqh;
1512 : : int rc;
1513 : :
1514 : 4 : logout_reqh = (struct iscsi_bhs_logout_req *)&pdu.bhs;
1515 : :
1516 : : /* Case 1 - Target can accept logout request only with the reason "close the session"
1517 : : * on discovery session.
1518 : : */
1519 : 4 : logout_reqh->reason = 1;
1520 : 4 : conn.sess = &sess;
1521 : 4 : sess.session_type = SESSION_TYPE_DISCOVERY;
1522 : :
1523 : 4 : rc = iscsi_pdu_hdr_op_logout(&conn, &pdu);
1524 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1525 : :
1526 : : /* Case 2 - Session is not established yet but connection was closed successfully. */
1527 : 4 : conn.sess = NULL;
1528 : 4 : conn.StatSN = 1234;
1529 : 4 : to_be32(&logout_reqh->exp_stat_sn, 1234);
1530 : 4 : pdu.cmd_sn = 5678;
1531 : :
1532 : 4 : rc = iscsi_pdu_hdr_op_logout(&conn, &pdu);
1533 : 4 : CU_ASSERT(rc == 0);
1534 : 4 : check_logout_response(0, 1234, 5678, 5678);
1535 : 4 : CU_ASSERT(conn.StatSN == 1235);
1536 : :
1537 : : /* Case 3 - Session type is normal but CID was not found. Hence connection or session
1538 : : * was not closed.
1539 : : */
1540 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
1541 : 4 : sess.ExpCmdSN = 5679;
1542 : 4 : sess.connections = 1;
1543 : 4 : conn.sess = &sess;
1544 : 4 : conn.cid = 1;
1545 : :
1546 : 4 : rc = iscsi_pdu_hdr_op_logout(&conn, &pdu);
1547 : 4 : CU_ASSERT(rc == 0);
1548 : 4 : check_logout_response(1, 1235, 5679, 1);
1549 : 4 : CU_ASSERT(conn.StatSN == 1236);
1550 : 4 : CU_ASSERT(sess.MaxCmdSN == 1);
1551 : :
1552 : : /* Case 4 - Session type is normal and CID was found. Connection or session was closed
1553 : : * successfully.
1554 : : */
1555 : 4 : to_be16(&logout_reqh->cid, 1);
1556 : :
1557 : 4 : rc = iscsi_pdu_hdr_op_logout(&conn, &pdu);
1558 : 4 : CU_ASSERT(rc == 0);
1559 : 4 : check_logout_response(0, 1236, 5679, 2);
1560 : 4 : CU_ASSERT(conn.StatSN == 1237);
1561 : 4 : CU_ASSERT(sess.MaxCmdSN == 2);
1562 : :
1563 : : /* Case 5 - PDU pool is empty. */
1564 : 4 : g_pdu_pool_is_empty = true;
1565 : :
1566 : 4 : rc = iscsi_pdu_hdr_op_logout(&conn, &pdu);
1567 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1568 : :
1569 : 4 : g_pdu_pool_is_empty = false;
1570 : 4 : }
1571 : :
1572 : : static void
1573 : 12 : check_scsi_task(struct spdk_iscsi_pdu *pdu, enum spdk_scsi_data_dir dir)
1574 : : {
1575 : : struct spdk_iscsi_task *task;
1576 : :
1577 : 12 : task = pdu->task;
1578 : 12 : CU_ASSERT(task != NULL);
1579 : 12 : CU_ASSERT(task->pdu == pdu);
1580 : 12 : CU_ASSERT(task->scsi.dxfer_dir == (uint32_t)dir);
1581 : :
1582 : 12 : iscsi_task_put(task);
1583 : 12 : pdu->task = NULL;
1584 : 12 : }
1585 : :
1586 : : static void
1587 : 4 : pdu_hdr_op_scsi_test(void)
1588 : : {
1589 : 4 : struct spdk_iscsi_sess sess = {};
1590 : 4 : struct spdk_iscsi_conn conn = {};
1591 : 4 : struct spdk_iscsi_pdu pdu = {};
1592 : 4 : struct spdk_scsi_dev dev = {};
1593 : 4 : struct spdk_scsi_lun lun = {};
1594 : : struct iscsi_bhs_scsi_req *scsi_reqh;
1595 : : int rc;
1596 : :
1597 : 4 : scsi_reqh = (struct iscsi_bhs_scsi_req *)&pdu.bhs;
1598 : :
1599 : 4 : conn.sess = &sess;
1600 : 4 : conn.dev = &dev;
1601 : :
1602 : : /* Case 1 - SCSI command is acceptable only on normal session. */
1603 : 4 : sess.session_type = SESSION_TYPE_DISCOVERY;
1604 : :
1605 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1606 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1607 : :
1608 : : /* Case 2 - Task pool is empty. */
1609 : 4 : g_task_pool_is_empty = true;
1610 : :
1611 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1612 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1613 : :
1614 : 4 : g_task_pool_is_empty = false;
1615 : :
1616 : : /* Case 3 - bidirectional operations (both R and W flags are set to 1) are not supported. */
1617 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
1618 : 4 : scsi_reqh->read_bit = 1;
1619 : 4 : scsi_reqh->write_bit = 1;
1620 : :
1621 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1622 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1623 : :
1624 : : /* Case 4 - LUN is hot-removed, and return immediately. */
1625 : 4 : scsi_reqh->write_bit = 0;
1626 : :
1627 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1628 : 4 : CU_ASSERT(rc == 0);
1629 : 4 : CU_ASSERT(pdu.task == NULL);
1630 : :
1631 : : /* Case 5 - SCSI read command PDU is correct, and the configured iSCSI task is set to the PDU. */
1632 : 4 : TAILQ_INIT(&dev.luns);
1633 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
1634 : :
1635 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1636 : 4 : CU_ASSERT(rc == 0);
1637 : 4 : check_scsi_task(&pdu, SPDK_SCSI_DIR_FROM_DEV);
1638 : :
1639 : : /* Case 6 - For SCSI write command PDU, its data segment length must not be more than
1640 : : * FirstBurstLength plus extra space to account for digests.
1641 : : */
1642 : 4 : scsi_reqh->read_bit = 0;
1643 : 4 : scsi_reqh->write_bit = 1;
1644 : 4 : pdu.data_segment_len = iscsi_get_max_immediate_data_size() + 1;
1645 : :
1646 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1647 : 4 : CU_ASSERT(rc == 0);
1648 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1649 : :
1650 : : /* Case 7 - For SCSI write command PDU, its data segment length must not be more than
1651 : : * Expected Data Transfer Length (EDTL).
1652 : : */
1653 : 4 : pdu.data_segment_len = iscsi_get_max_immediate_data_size();
1654 : 4 : to_be32(&scsi_reqh->expected_data_xfer_len, pdu.data_segment_len - 1);
1655 : :
1656 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1657 : 4 : CU_ASSERT(rc == 0);
1658 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1659 : :
1660 : : /* Case 8 - If ImmediateData is not enabled for the session, SCSI write command PDU
1661 : : * cannot have data segment.
1662 : : */
1663 : 4 : to_be32(&scsi_reqh->expected_data_xfer_len, pdu.data_segment_len);
1664 : :
1665 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1666 : 4 : CU_ASSERT(rc == 0);
1667 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1668 : :
1669 : : /* Case 9 - For SCSI write command PDU, its data segment length must not be more
1670 : : * than FirstBurstLength.
1671 : : */
1672 : 4 : sess.ImmediateData = true;
1673 : :
1674 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1675 : 4 : CU_ASSERT(rc == 0);
1676 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1677 : :
1678 : : /* Case 10 - SCSI write command PDU is correct, and the configured iSCSI task is set to the PDU. */
1679 : 4 : sess.FirstBurstLength = pdu.data_segment_len;
1680 : :
1681 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1682 : 4 : CU_ASSERT(rc == 0);
1683 : 4 : check_scsi_task(&pdu, SPDK_SCSI_DIR_TO_DEV);
1684 : :
1685 : : /* Case 11 - R and W must not both be 0 when EDTL is not 0. */
1686 : 4 : scsi_reqh->write_bit = 0;
1687 : :
1688 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1689 : 4 : CU_ASSERT(rc == 0);
1690 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_INVALID_PDU_FIELD);
1691 : :
1692 : : /* Case 11 - R and W are both 0 and EDTL is also 0, and hence SCSI command PDU is accepted. */
1693 : 4 : to_be32(&scsi_reqh->expected_data_xfer_len, 0);
1694 : :
1695 : 4 : rc = iscsi_pdu_hdr_op_scsi(&conn, &pdu);
1696 : 4 : CU_ASSERT(rc == 0);
1697 : 4 : check_scsi_task(&pdu, SPDK_SCSI_DIR_NONE);
1698 : 4 : }
1699 : :
1700 : : static void
1701 : 28 : check_iscsi_task_mgmt_response(uint8_t response, uint32_t task_tag, uint32_t stat_sn,
1702 : : uint32_t exp_cmd_sn, uint32_t max_cmd_sn)
1703 : : {
1704 : : struct spdk_iscsi_pdu *rsp_pdu;
1705 : : struct iscsi_bhs_task_resp *rsph;
1706 : :
1707 : 28 : rsp_pdu = TAILQ_FIRST(&g_write_pdu_list);
1708 : 28 : CU_ASSERT(rsp_pdu != NULL);
1709 : 28 : rsph = (struct iscsi_bhs_task_resp *)&rsp_pdu->bhs;
1710 : 28 : CU_ASSERT(rsph->response == response);
1711 : 28 : CU_ASSERT(from_be32(&rsph->itt) == task_tag);
1712 : 28 : CU_ASSERT(from_be32(&rsph->exp_cmd_sn) == exp_cmd_sn);
1713 : 28 : CU_ASSERT(from_be32(&rsph->max_cmd_sn) == max_cmd_sn);
1714 : :
1715 [ + + ]: 28 : TAILQ_REMOVE(&g_write_pdu_list, rsp_pdu, tailq);
1716 : 28 : iscsi_put_pdu(rsp_pdu);
1717 : 28 : }
1718 : :
1719 : : static void
1720 : 4 : pdu_hdr_op_task_mgmt_test(void)
1721 : : {
1722 : 4 : struct spdk_iscsi_sess sess = {};
1723 : 4 : struct spdk_iscsi_conn conn = {};
1724 : 4 : struct spdk_iscsi_pdu pdu = {};
1725 : 4 : struct spdk_scsi_dev dev = {};
1726 : 4 : struct spdk_scsi_lun lun = {};
1727 : : struct iscsi_bhs_task_req *task_reqh;
1728 : : int rc;
1729 : :
1730 : : /* TBD: This test covers only error paths before creating iSCSI task for now.
1731 : : * Testing iSCSI task creation in iscsi_pdu_hdr_op_task() by UT is not simple
1732 : : * and do it separately later.
1733 : : */
1734 : :
1735 : 4 : task_reqh = (struct iscsi_bhs_task_req *)&pdu.bhs;
1736 : :
1737 : 4 : conn.sess = &sess;
1738 : 4 : conn.dev = &dev;
1739 : :
1740 : : /* Case 1 - Task Management Function request PDU is acceptable only on normal session. */
1741 : 4 : sess.session_type = SESSION_TYPE_DISCOVERY;
1742 : :
1743 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1744 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1745 : :
1746 : : /* Case 2 - LUN is hot removed. "LUN does not exist" response is sent. */
1747 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
1748 : 4 : task_reqh->immediate = 0;
1749 : 4 : to_be32(&task_reqh->itt, 1234);
1750 : :
1751 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1752 : 4 : CU_ASSERT(rc == 0);
1753 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_RESP_LUN_NOT_EXIST, 1234, 0, 0, 1);
1754 : :
1755 : : /* Case 3 - Unassigned function is specified. "Function rejected" response is sent. */
1756 : 4 : TAILQ_INIT(&dev.luns);
1757 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
1758 : 4 : task_reqh->flags = 0;
1759 : :
1760 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1761 : 4 : CU_ASSERT(rc == 0);
1762 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_REJECTED, 1234, 0, 0, 2);
1763 : :
1764 : : /* Case 4 - CLEAR TASK SET is not supported. "Task management function not supported"
1765 : : * response is sent.
1766 : : */
1767 : 4 : task_reqh->flags = ISCSI_TASK_FUNC_CLEAR_TASK_SET;
1768 : :
1769 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1770 : 4 : CU_ASSERT(rc == 0);
1771 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED, 1234, 0, 0, 3);
1772 : :
1773 : : /* Case 5 - CLEAR ACA is not supported. "Task management function not supported" is sent. */
1774 : 4 : task_reqh->flags = ISCSI_TASK_FUNC_CLEAR_ACA;
1775 : :
1776 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1777 : 4 : CU_ASSERT(rc == 0);
1778 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED, 1234, 0, 0, 4);
1779 : :
1780 : : /* Case 6 - TARGET WARM RESET is not supported. "Task management function not supported
1781 : : * is sent.
1782 : : */
1783 : 4 : task_reqh->flags = ISCSI_TASK_FUNC_TARGET_WARM_RESET;
1784 : :
1785 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1786 : 4 : CU_ASSERT(rc == 0);
1787 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED, 1234, 0, 0, 5);
1788 : :
1789 : : /* Case 7 - TARGET COLD RESET is not supported. "Task management function not supported
1790 : : * is sent.
1791 : : */
1792 : 4 : task_reqh->flags = ISCSI_TASK_FUNC_TARGET_COLD_RESET;
1793 : :
1794 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1795 : 4 : CU_ASSERT(rc == 0);
1796 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED, 1234, 0, 0, 6);
1797 : :
1798 : : /* Case 8 - TASK REASSIGN is not supported. "Task management function not supported" is sent. */
1799 : 4 : task_reqh->flags = ISCSI_TASK_FUNC_TASK_REASSIGN;
1800 : :
1801 : 4 : rc = iscsi_pdu_hdr_op_task(&conn, &pdu);
1802 : 4 : CU_ASSERT(rc == 0);
1803 : 4 : check_iscsi_task_mgmt_response(ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED, 1234, 0, 0, 7);
1804 : 4 : }
1805 : :
1806 : : static void
1807 : 4 : pdu_hdr_op_nopout_test(void)
1808 : : {
1809 : 4 : struct spdk_iscsi_sess sess = {};
1810 : 4 : struct spdk_iscsi_conn conn = {};
1811 : 4 : struct spdk_iscsi_pdu pdu = {};
1812 : : struct iscsi_bhs_nop_out *nopout_reqh;
1813 : : int rc;
1814 : :
1815 : 4 : nopout_reqh = (struct iscsi_bhs_nop_out *)&pdu.bhs;
1816 : :
1817 : 4 : conn.sess = &sess;
1818 : :
1819 : : /* Case 1 - NOP-Out PDU is acceptable only on normal session. */
1820 : 4 : sess.session_type = SESSION_TYPE_DISCOVERY;
1821 : :
1822 : 4 : rc = iscsi_pdu_hdr_op_nopout(&conn, &pdu);
1823 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1824 : :
1825 : : /* Case 2 - The length of the reflected ping data is limited to MaxRecvDataSegmentLength. */
1826 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
1827 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH + 1;
1828 : :
1829 : 4 : rc = iscsi_pdu_hdr_op_nopout(&conn, &pdu);
1830 : 4 : CU_ASSERT(rc == 0);
1831 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1832 : :
1833 : : /* Case 3 - If Initiator Task Tag contains 0xffffffff, the I bit must be set
1834 : : * to 1 and Target Transfer Tag should be copied from NOP-In PDU. This case
1835 : : * satisfies the former but doesn't satisfy the latter, but ignore the error
1836 : : * for now.
1837 : : */
1838 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1839 : 4 : conn.id = 1234;
1840 : 4 : to_be32(&nopout_reqh->ttt, 1235);
1841 : 4 : to_be32(&nopout_reqh->itt, 0xffffffffU);
1842 : 4 : nopout_reqh->immediate = 1;
1843 : :
1844 : 4 : rc = iscsi_pdu_hdr_op_nopout(&conn, &pdu);
1845 : 4 : CU_ASSERT(rc == 0);
1846 : :
1847 : : /* Case 4 - This case doesn't satisfy the above former. This error is not ignored. */
1848 : 4 : nopout_reqh->immediate = 0;
1849 : :
1850 : 4 : rc = iscsi_pdu_hdr_op_nopout(&conn, &pdu);
1851 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1852 : 4 : }
1853 : :
1854 : : static void
1855 : 4 : check_iscsi_r2t(struct spdk_iscsi_task *task, uint32_t len)
1856 : : {
1857 : : struct spdk_iscsi_pdu *rsp_pdu;
1858 : : struct iscsi_bhs_r2t *rsph;
1859 : :
1860 : 4 : rsp_pdu = TAILQ_FIRST(&g_write_pdu_list);
1861 : 4 : CU_ASSERT(rsp_pdu != NULL);
1862 : 4 : rsph = (struct iscsi_bhs_r2t *)&rsp_pdu->bhs;
1863 : 4 : CU_ASSERT(rsph->opcode == ISCSI_OP_R2T);
1864 : 4 : CU_ASSERT(from_be64(&rsph->lun) == spdk_scsi_lun_id_int_to_fmt(task->lun_id));
1865 : 4 : CU_ASSERT(from_be32(&rsph->buffer_offset) + len == task->next_r2t_offset);
1866 : 4 : CU_ASSERT(from_be32(&rsph->desired_xfer_len) == len);
1867 : :
1868 [ + + ]: 4 : TAILQ_REMOVE(&g_write_pdu_list, rsp_pdu, tailq);
1869 : 4 : iscsi_put_pdu(rsp_pdu);
1870 : 4 : }
1871 : :
1872 : : static void
1873 : 4 : pdu_hdr_op_data_test(void)
1874 : : {
1875 : 4 : struct spdk_iscsi_sess sess = {};
1876 : 4 : struct spdk_iscsi_conn conn = {};
1877 : 4 : struct spdk_iscsi_pdu pdu = {};
1878 : 4 : struct spdk_iscsi_task primary = {};
1879 : 4 : struct spdk_scsi_dev dev = {};
1880 : 4 : struct spdk_scsi_lun lun = {};
1881 : : struct iscsi_bhs_data_out *data_reqh;
1882 : : int rc;
1883 : :
1884 : 4 : data_reqh = (struct iscsi_bhs_data_out *)&pdu.bhs;
1885 : :
1886 : 4 : conn.sess = &sess;
1887 : 4 : conn.dev = &dev;
1888 : 4 : TAILQ_INIT(&conn.active_r2t_tasks);
1889 : :
1890 : : /* Case 1 - SCSI Data-Out PDU is acceptable only on normal session. */
1891 : 4 : sess.session_type = SESSION_TYPE_DISCOVERY;
1892 : :
1893 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1894 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1895 : :
1896 : : /* Case 2 - Data segment length must not be more than MaxRecvDataSegmentLength. */
1897 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
1898 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH + 1;
1899 : :
1900 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1901 : 4 : CU_ASSERT(rc == 0);
1902 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1903 : :
1904 : : /* Case 3 - R2T task whose Target Transfer Tag matches is not found. */
1905 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1906 : :
1907 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1908 : 4 : CU_ASSERT(rc == 0);
1909 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_INVALID_PDU_FIELD);
1910 : :
1911 : : /* Case 4 - R2T task whose Target Transfer Tag matches is found but data segment length
1912 : : * is more than Desired Data Transfer Length of the R2T.
1913 : : */
1914 : 4 : primary.desired_data_transfer_length = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 1;
1915 : 4 : conn.pending_r2t = 1;
1916 : 4 : TAILQ_INSERT_TAIL(&conn.active_r2t_tasks, &primary, link);
1917 : :
1918 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1919 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1920 : :
1921 : : /* Case 5 - Initiator task tag doesn't match tag of R2T task. */
1922 : 4 : primary.desired_data_transfer_length = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
1923 : 4 : to_be32(&data_reqh->itt, 1);
1924 : :
1925 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1926 : 4 : CU_ASSERT(rc == 0);
1927 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_INVALID_PDU_FIELD);
1928 : :
1929 : : /* Case 6 - DataSN doesn't match the Data-Out PDU number within the current
1930 : : * output sequence.
1931 : : */
1932 : 4 : to_be32(&data_reqh->itt, 0);
1933 : 4 : to_be32(&data_reqh->data_sn, 1);
1934 : :
1935 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1936 : 4 : CU_ASSERT(rc == 0);
1937 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1938 : :
1939 : : /* Case 7 - Output sequence must be in increasing buffer offset and must not
1940 : : * be overlaid but they are not satisfied.
1941 : : */
1942 : 4 : to_be32(&data_reqh->data_sn, 0);
1943 : 4 : to_be32(&data_reqh->buffer_offset, 4096);
1944 : :
1945 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1946 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1947 : :
1948 : : /* Case 8 - Data segment length must not exceed MaxBurstLength. */
1949 : 4 : to_be32(&data_reqh->buffer_offset, 0);
1950 : 4 : sess.MaxBurstLength = pdu.data_segment_len - 1;
1951 : :
1952 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1953 : 4 : CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
1954 : :
1955 : : /* Case 9 - LUN is hot removed. */
1956 : 4 : sess.MaxBurstLength = pdu.data_segment_len * 4;
1957 : 4 : to_be32(&data_reqh->data_sn, primary.r2t_datasn);
1958 : 4 : to_be32(&data_reqh->buffer_offset, primary.next_expected_r2t_offset);
1959 : :
1960 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1961 : 4 : CU_ASSERT(rc == 0);
1962 : 4 : check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
1963 : :
1964 : : /* Case 10 - SCSI Data-Out PDU is correct and processed. Its F bit is 0 and hence
1965 : : * R2T is not sent.
1966 : : */
1967 : 4 : TAILQ_INIT(&dev.luns);
1968 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
1969 : 4 : to_be32(&data_reqh->data_sn, primary.r2t_datasn);
1970 : 4 : to_be32(&data_reqh->buffer_offset, primary.next_expected_r2t_offset);
1971 : :
1972 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1973 : 4 : CU_ASSERT(rc == 0);
1974 [ - + ]: 4 : CU_ASSERT(!pdu.is_rejected);
1975 : 4 : CU_ASSERT(pdu.data_buf_len == SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
1976 : 4 : pdu.task = NULL;
1977 : :
1978 : : /* Case 11 - SCSI Data-Out PDU is correct and processed. Its F bit is 1 and hence
1979 : : * R2T is sent.
1980 : : */
1981 : 4 : data_reqh->flags |= ISCSI_FLAG_FINAL;
1982 : 4 : to_be32(&data_reqh->data_sn, primary.r2t_datasn);
1983 : 4 : to_be32(&data_reqh->buffer_offset, primary.next_expected_r2t_offset);
1984 : 4 : primary.scsi.transfer_len = pdu.data_segment_len * 5;
1985 : :
1986 : 4 : rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
1987 : 4 : CU_ASSERT(rc == 0);
1988 [ - + ]: 4 : CU_ASSERT(!pdu.is_rejected);
1989 : 4 : check_iscsi_r2t(&primary, pdu.data_segment_len * 4);
1990 : 4 : }
1991 : :
1992 : : /* Test an ISCSI_OP_TEXT PDU with CONTINUE bit set but
1993 : : * no data.
1994 : : */
1995 : : static void
1996 : 4 : empty_text_with_cbit_test(void)
1997 : : {
1998 : 4 : struct spdk_iscsi_sess sess = {};
1999 : 4 : struct spdk_iscsi_conn conn = {};
2000 : 4 : struct spdk_scsi_dev dev = {};
2001 : : struct spdk_iscsi_pdu *req_pdu;
2002 : : int rc;
2003 : :
2004 : 4 : req_pdu = iscsi_get_pdu(&conn);
2005 : :
2006 : 4 : sess.ExpCmdSN = 0;
2007 : 4 : sess.MaxCmdSN = 64;
2008 : 4 : sess.session_type = SESSION_TYPE_NORMAL;
2009 : 4 : sess.MaxBurstLength = 1024;
2010 : :
2011 : 4 : conn.full_feature = 1;
2012 : 4 : conn.sess = &sess;
2013 : 4 : conn.dev = &dev;
2014 : 4 : conn.state = ISCSI_CONN_STATE_RUNNING;
2015 : :
2016 [ - + ]: 4 : memset(&req_pdu->bhs, 0, sizeof(req_pdu->bhs));
2017 : 4 : req_pdu->bhs.opcode = ISCSI_OP_TEXT;
2018 : 4 : req_pdu->bhs.flags = ISCSI_TEXT_CONTINUE;
2019 : :
2020 : 4 : rc = iscsi_pdu_hdr_handle(&conn, req_pdu);
2021 : 4 : CU_ASSERT(rc == 0);
2022 [ - + ]: 4 : CU_ASSERT(!req_pdu->is_rejected);
2023 : 4 : rc = iscsi_pdu_payload_handle(&conn, req_pdu);
2024 : 4 : CU_ASSERT(rc == 0);
2025 : :
2026 : 4 : iscsi_put_pdu(req_pdu);
2027 : 4 : }
2028 : :
2029 : : static void
2030 : 68 : check_pdu_payload_read(struct spdk_iscsi_pdu *pdu, struct spdk_mobj *mobj,
2031 : : int rc, int index, uint32_t read_offset)
2032 : : {
2033 : : uint64_t buf_offset;
2034 : : uint32_t *data;
2035 : : uint32_t i;
2036 : :
2037 : 68 : data = (uint32_t *)pdu->data;
2038 : 68 : buf_offset = (uint64_t)pdu->data - (uint64_t)mobj->buf;
2039 : :
2040 : 68 : CU_ASSERT(pdu->mobj[index] == mobj);
2041 [ - + ]: 68 : CU_ASSERT(pdu->data_from_mempool == true);
2042 [ + + + - ]: 68 : CU_ASSERT(buf_offset == 0 || pdu->data_offset == 0);
2043 : 68 : CU_ASSERT(mobj->data_len + pdu->data_offset == buf_offset + pdu->data_valid_bytes);
2044 [ + + + - ]: 68 : CU_ASSERT(rc > 0 || pdu->data_valid_bytes == pdu->data_segment_len);
2045 : :
2046 [ + + ]: 368776 : for (i = 0; i < pdu->data_valid_bytes - pdu->data_offset; i += 4) {
2047 : 368708 : CU_ASSERT(data[i / 4] == (uint32_t)(read_offset + i));
2048 : 92177 : }
2049 : 68 : }
2050 : :
2051 : : static void
2052 : 4 : pdu_payload_read_test(void)
2053 : : {
2054 : 4 : struct spdk_iscsi_conn conn = {};
2055 : 4 : struct spdk_iscsi_pdu pdu = {};
2056 : 4 : struct spdk_mobj mobj1 = {}, mobj2 = {};
2057 : : int rc;
2058 : :
2059 : 4 : g_iscsi.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
2060 : :
2061 : 4 : alloc_mock_mobj(&mobj1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2062 : 4 : alloc_mock_mobj(&mobj2, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2063 : :
2064 : 4 : MOCK_SET(spdk_mempool_get, &mobj1);
2065 : :
2066 : : /* The following tests assume that a iscsi_conn_read_data() call could read
2067 : : * the required length of the data and all read lengths are 4 bytes multiples.
2068 : : * The latter is to verify data is copied to the correct offset by using data patterns.
2069 : : */
2070 : :
2071 : : /* Case 1: data segment size is equal with max immediate data size. */
2072 : 4 : pdu.data_segment_len = iscsi_get_max_immediate_data_size();
2073 : 4 : pdu.data_buf_len = pdu.data_segment_len;
2074 : 4 : g_conn_read_len = 0;
2075 : :
2076 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2077 : 4 : check_pdu_payload_read(&pdu, &mobj1, rc, 0, 0);
2078 : :
2079 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2080 : 4 : mobj1.data_len = 0;
2081 : :
2082 : : /* Case 2: data segment size is equal with SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH. */
2083 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
2084 : 4 : pdu.data_buf_len = pdu.data_segment_len;
2085 : 4 : g_conn_read_len = 0;
2086 : :
2087 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2088 : 4 : check_pdu_payload_read(&pdu, &mobj1, rc, 0, 0);
2089 : :
2090 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2091 : 4 : mobj1.data_len = 0;
2092 : :
2093 : : /* Case 3: data segment size is larger than SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH.
2094 : : * This should result in error.
2095 : : */
2096 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH + 1;
2097 : 4 : pdu.data_buf_len = pdu.data_segment_len;
2098 : 4 : g_conn_read_len = 0;
2099 : :
2100 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2101 : 4 : CU_ASSERT(rc < 0);
2102 : :
2103 : : /* Case 4: read starts from the middle of the 1st data buffer, the 1st data buffer
2104 : : * ran out, allocate the 2nd data buffer, and read the remaining data to the 2nd
2105 : : * data buffer.
2106 : : */
2107 : 4 : mobj1.data_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2;
2108 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
2109 : 4 : pdu.data_buf_len = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2110 : 4 : pdu.mobj[0] = &mobj1;
2111 : 4 : pdu.data = (void *)((uint64_t)mobj1.buf + SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2);
2112 : 4 : pdu.data_from_mempool = true;
2113 : 4 : g_conn_read_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2;
2114 : :
2115 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2116 : 4 : check_pdu_payload_read(&pdu, &mobj1, rc, 0, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2);
2117 : :
2118 : 4 : MOCK_SET(spdk_mempool_get, &mobj2);
2119 : :
2120 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2121 : 4 : check_pdu_payload_read(&pdu, &mobj2, rc, 1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2122 : :
2123 : : /* Case 5: data segment size is SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH, data digest
2124 : : * is enabled, and reading PDU data is split between data segment and data digest.
2125 : : */
2126 : 4 : conn.data_digest = true;
2127 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2128 : 4 : pdu.crc32c = SPDK_CRC32C_INITIAL;
2129 : 4 : pdu.data = mobj1.buf;
2130 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
2131 : 4 : pdu.mobj[0] = &mobj1;
2132 : 4 : pdu.data_valid_bytes = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
2133 : 4 : mobj1.data_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
2134 : :
2135 : : /* generate data digest. */
2136 : 4 : g_data_digest = spdk_crc32c_update(mobj1.buf, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH,
2137 : : SPDK_CRC32C_INITIAL);
2138 : 4 : g_data_digest ^= SPDK_CRC32C_XOR;
2139 : 4 : g_conn_read_data_digest = true;
2140 : :
2141 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2142 : 4 : CU_ASSERT(rc == 0);
2143 : 4 : CU_ASSERT(pdu.ddigest_valid_bytes == ISCSI_DIGEST_LEN);
2144 : 4 : CU_ASSERT(pdu.mobj[1] == NULL);
2145 : :
2146 : 4 : g_conn_read_data_digest = false;
2147 : 4 : g_conn_read_len = 0;
2148 : 4 : MOCK_SET(spdk_mempool_get, &mobj1);
2149 : 4 : mobj1.data_len = 0;
2150 : :
2151 : 4 : g_conn_read_len = 0;
2152 [ - + - + ]: 4 : MOCK_CLEAR(spdk_mempool_get);
2153 : :
2154 : 4 : free(mobj1.buf);
2155 : 4 : free(mobj2.buf);
2156 : 4 : }
2157 : :
2158 : : static void
2159 : 40 : check_pdu_hdr_handle(struct spdk_iscsi_pdu *pdu, struct spdk_mobj *mobj, uint32_t offset,
2160 : : struct spdk_iscsi_task *primary)
2161 : : {
2162 : 40 : CU_ASSERT(pdu->mobj[0] == mobj);
2163 [ + + + - ]: 40 : CU_ASSERT(pdu->data == NULL || pdu->data == (void *)((uint64_t)mobj->buf + offset));
2164 : 40 : CU_ASSERT(primary->mobj == NULL);
2165 : 40 : }
2166 : :
2167 : : static void
2168 : 44 : check_pdu_payload_handle(struct spdk_iscsi_pdu *pdu, struct spdk_iscsi_task *primary,
2169 : : struct spdk_mobj *pdu_mobj0, struct spdk_mobj *pdu_mobj1,
2170 : : struct spdk_mobj *primary_mobj, uint32_t primary_offset)
2171 : : {
2172 : 44 : CU_ASSERT(pdu->mobj[0] == pdu_mobj0);
2173 : 44 : CU_ASSERT(pdu->mobj[1] == pdu_mobj1);
2174 : 44 : CU_ASSERT(primary->mobj == primary_mobj);
2175 : 44 : CU_ASSERT(primary->current_data_offset == primary_offset);
2176 : 44 : }
2177 : :
2178 : : static void
2179 : 16 : check_write_subtask_submit(struct spdk_scsi_lun *lun, struct spdk_mobj *mobj,
2180 : : struct spdk_iscsi_pdu *pdu,
2181 : : int index, uint32_t offset, uint32_t length)
2182 : : {
2183 : : struct spdk_scsi_task *scsi_task;
2184 : : struct spdk_iscsi_task *subtask;
2185 : : uint32_t *data;
2186 : : uint32_t i;
2187 : :
2188 : 16 : scsi_task = TAILQ_FIRST(&lun->tasks);
2189 [ + + ]: 16 : SPDK_CU_ASSERT_FATAL(scsi_task != NULL);
2190 [ + + ]: 16 : TAILQ_REMOVE(&lun->tasks, scsi_task, scsi_link);
2191 : :
2192 : 16 : subtask = iscsi_task_from_scsi_task(scsi_task);
2193 : :
2194 : 16 : CU_ASSERT(iscsi_task_get_pdu(subtask) == pdu);
2195 : 16 : CU_ASSERT(pdu->mobj[index] == mobj);
2196 : 16 : CU_ASSERT(subtask->scsi.offset == offset);
2197 : 16 : CU_ASSERT(subtask->scsi.length == length);
2198 : 16 : CU_ASSERT(subtask->scsi.iovs[0].iov_base == mobj->buf);
2199 : 16 : CU_ASSERT(subtask->scsi.iovs[0].iov_len == length);
2200 : :
2201 : 16 : data = (uint32_t *)mobj->buf;
2202 [ + + ]: 229392 : for (i = 0; i < length; i += 4) {
2203 : 229376 : CU_ASSERT(data[i / 4] == offset + i);
2204 : 57344 : }
2205 : :
2206 : 16 : free(subtask);
2207 : 16 : }
2208 : :
2209 : : static void
2210 : 4 : data_out_pdu_sequence_test(void)
2211 : : {
2212 : 4 : struct spdk_scsi_lun lun = { .tasks = TAILQ_HEAD_INITIALIZER(lun.tasks), };
2213 : 4 : struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
2214 : 4 : struct spdk_iscsi_sess sess = {
2215 : : .session_type = SESSION_TYPE_NORMAL,
2216 : : .MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH,
2217 : : };
2218 : 4 : struct spdk_iscsi_conn conn = {
2219 : : .full_feature = true,
2220 : : .state = ISCSI_CONN_STATE_RUNNING,
2221 : : .sess = &sess,
2222 : : .dev = &dev,
2223 : 1 : .active_r2t_tasks = TAILQ_HEAD_INITIALIZER(conn.active_r2t_tasks),
2224 : : };
2225 : 4 : struct spdk_iscsi_task primary = {};
2226 : 4 : struct spdk_iscsi_pdu pdu = {};
2227 : 4 : struct spdk_mobj mobj1 = {}, mobj2 = {}, mobj3 = {};
2228 : : struct iscsi_bhs_data_out *data_reqh;
2229 : : int rc;
2230 : :
2231 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
2232 : :
2233 : 4 : alloc_mock_mobj(&mobj1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2234 : 4 : alloc_mock_mobj(&mobj2, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2235 : 4 : alloc_mock_mobj(&mobj3, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2236 : :
2237 : : /* Test scenario is as follows.
2238 : : *
2239 : : * Some iSCSI initiator sends a Data-OUT PDU sequence such that the size of
2240 : : * the data segment of any Data-OUT PDU is not block size multiples.
2241 : : * Test if such complex Data-OUT PDU sequence is processed correctly.
2242 : : *
2243 : : * Desired Data Transfer Length is 5 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2.
2244 : : * Number of Data-OUT PDUs is 4. Length of the data segment of the first two PDUs are
2245 : : * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 - 4. Length of the data segment of the
2246 : : * third PDU is SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH. Length of the data segment
2247 : : * of the final PDU is SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 + 8.
2248 : : *
2249 : : * Three data buffers should be used and three subtasks should be created and submitted.
2250 : : *
2251 : : * The test scenario assume that a iscsi_conn_read_data() call could read
2252 : : * the required length of the data and all read lengths are 4 bytes multiples.
2253 : : * The latter is to verify data is copied to the correct offset by using data patterns.
2254 : : */
2255 : :
2256 : 4 : primary.scsi.transfer_len = 5 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2;
2257 : 4 : primary.desired_data_transfer_length = primary.scsi.transfer_len;
2258 : 4 : TAILQ_INSERT_TAIL(&conn.active_r2t_tasks, &primary, link);
2259 : 4 : conn.pending_r2t = 1;
2260 : 4 : g_conn_read_len = 0;
2261 : :
2262 : : /* The 1st Data-OUT PDU */
2263 : 4 : data_reqh = (struct iscsi_bhs_data_out *)&pdu.bhs;
2264 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI_DATAOUT;
2265 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 - 4;
2266 : :
2267 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2268 : 4 : CU_ASSERT(rc == 0);
2269 : 4 : check_pdu_hdr_handle(&pdu, NULL, 0, &primary);
2270 : :
2271 : 4 : MOCK_SET(spdk_mempool_get, &mobj1);
2272 : :
2273 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2274 : 4 : CU_ASSERT(rc == 0);
2275 : 4 : check_pdu_payload_read(&pdu, &mobj1, rc, 0, 0);
2276 : :
2277 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2278 : 4 : CU_ASSERT(rc == 0);
2279 : 4 : check_pdu_payload_handle(&pdu, &primary, NULL, NULL, &mobj1, 0);
2280 : :
2281 : : /* The 2nd Data-OUT PDU */
2282 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2283 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI_DATAOUT;
2284 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 - 4;
2285 : 4 : to_be32(&data_reqh->data_sn, 1);
2286 : 4 : to_be32(&data_reqh->buffer_offset, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 - 4);
2287 : :
2288 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2289 : 4 : CU_ASSERT(rc == 0);
2290 : 4 : check_pdu_hdr_handle(&pdu, &mobj1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 - 4, &primary);
2291 : :
2292 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2293 : 4 : CU_ASSERT(rc == 0);
2294 : 4 : check_pdu_payload_read(&pdu, &mobj1, rc, 0, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 - 4);
2295 : :
2296 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2297 : 4 : CU_ASSERT(rc == 0);
2298 : 4 : check_pdu_payload_handle(&pdu, &primary, NULL, NULL, &mobj1, 0);
2299 : :
2300 : : /* The 3rd Data-OUT PDU */
2301 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2302 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI_DATAOUT;
2303 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
2304 : 4 : to_be32(&data_reqh->data_sn, 2);
2305 : 4 : to_be32(&data_reqh->buffer_offset, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 8);
2306 : :
2307 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2308 : 4 : CU_ASSERT(rc == 0);
2309 : 4 : check_pdu_hdr_handle(&pdu, &mobj1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 8, &primary);
2310 : :
2311 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2312 : 4 : CU_ASSERT(rc > 0);
2313 : 4 : check_pdu_payload_read(&pdu, &mobj1, rc, 0, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 8);
2314 : :
2315 : 4 : MOCK_SET(spdk_mempool_get, &mobj2);
2316 : :
2317 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2318 : 4 : CU_ASSERT(rc == 0);
2319 : 4 : check_pdu_payload_read(&pdu, &mobj2, rc, 1, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2320 : :
2321 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2322 : 4 : CU_ASSERT(rc == 0);
2323 : 4 : check_pdu_payload_handle(&pdu, &primary, &mobj1, NULL, &mobj2,
2324 : : SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2325 : :
2326 : 4 : check_write_subtask_submit(&lun, &mobj1, &pdu, 0, 0, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2327 : :
2328 : : /* The 4th and final Data-OUT PDU */
2329 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2330 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI_DATAOUT;
2331 : 4 : pdu.data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2 + 8;
2332 : 4 : data_reqh->flags |= ISCSI_FLAG_FINAL;
2333 : 4 : to_be32(&data_reqh->data_sn, 3);
2334 : 4 : to_be32(&data_reqh->buffer_offset, 2 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 8);
2335 : :
2336 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2337 : 4 : CU_ASSERT(rc == 0);
2338 : 4 : check_pdu_hdr_handle(&pdu, &mobj2, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 8, &primary);
2339 : :
2340 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2341 : 4 : CU_ASSERT(rc > 0);
2342 : 4 : check_pdu_payload_read(&pdu, &mobj2, rc, 0, 2 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH - 8);
2343 : :
2344 : 4 : MOCK_SET(spdk_mempool_get, &mobj3);
2345 : :
2346 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2347 : 4 : CU_ASSERT(rc == 0);
2348 : 4 : check_pdu_payload_read(&pdu, &mobj3, rc, 1, 2 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2349 : :
2350 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2351 : 4 : CU_ASSERT(rc == 0);
2352 : 4 : check_pdu_payload_handle(&pdu, &primary, &mobj2, &mobj3, NULL,
2353 : : 5 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2);
2354 : :
2355 : 4 : check_write_subtask_submit(&lun, &mobj2, &pdu, 0, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH,
2356 : : SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2357 : :
2358 : 4 : check_write_subtask_submit(&lun, &mobj3, &pdu, 1, 2 * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH,
2359 : : SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH / 2);
2360 : :
2361 : 4 : CU_ASSERT(TAILQ_EMPTY(&lun.tasks));
2362 : :
2363 [ - + - + ]: 4 : MOCK_CLEAR(spdk_mempool_get);
2364 : :
2365 : 4 : free(mobj1.buf);
2366 : 4 : free(mobj2.buf);
2367 : 4 : free(mobj3.buf);
2368 : 4 : }
2369 : :
2370 : : static void
2371 : 4 : immediate_data_and_data_out_pdu_sequence_test(void)
2372 : : {
2373 : 4 : struct spdk_scsi_lun lun = { .tasks = TAILQ_HEAD_INITIALIZER(lun.tasks), };
2374 : 4 : struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
2375 : 4 : struct spdk_iscsi_sess sess = {
2376 : : .session_type = SESSION_TYPE_NORMAL,
2377 : : .MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH,
2378 : : .ImmediateData = true,
2379 : : .FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH,
2380 : : };
2381 : 4 : struct spdk_iscsi_conn conn = {
2382 : : .full_feature = true,
2383 : : .state = ISCSI_CONN_STATE_RUNNING,
2384 : : .sess = &sess,
2385 : : .dev = &dev,
2386 : 1 : .active_r2t_tasks = TAILQ_HEAD_INITIALIZER(conn.active_r2t_tasks),
2387 : : .ttt = 1,
2388 : : };
2389 : 4 : struct spdk_iscsi_pdu pdu = {};
2390 : 4 : struct spdk_mobj mobj = {};
2391 : : struct spdk_iscsi_task *primary;
2392 : : struct iscsi_bhs_scsi_req *scsi_reqh;
2393 : : struct iscsi_bhs_data_out *data_reqh;
2394 : : int rc;
2395 : :
2396 : 4 : TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
2397 : :
2398 : 4 : alloc_mock_mobj(&mobj, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2399 : :
2400 : : /* Test scenario is as follows.
2401 : : *
2402 : : * Some iSCSI initiator sends an immediate data and more solicited data
2403 : : * through R2T within the same SCSI write such that the size of the data
2404 : : * segment of a SCSI Write PDU or any Data-OUT PDU is not block size multiples.
2405 : : * Test if such complex SCSI write is processed correctly.
2406 : : *
2407 : : * Desired Data Transfer Length of a SCSI Write is 65536.
2408 : : * PDU sequences are:
2409 : : * Host sent SCSI Write with 5792 bytes and F = 1
2410 : : * Target sent a R2T
2411 : : * Host sent Data-OUT with 15880 bytes
2412 : : * Host sent Data-OUT with 11536 bytes
2413 : : * Host sent Data-OUT with 2848 bytes
2414 : : * Host sent Data-OUT with 11536 bytes
2415 : : * Host sent Data-OUT with 5744 bytes
2416 : : * Host sent Data-OUT with 12200 bytes and F = 1
2417 : : *
2418 : : * One data buffer should be used and one subtask should be created and submitted.
2419 : : *
2420 : : * The test scenario assume that a iscsi_conn_read_data() call could read
2421 : : * the required length of the data and all read lengths are 4 bytes multiples.
2422 : : * The latter is to verify data is copied to the correct offset by using data patterns.
2423 : : */
2424 : :
2425 : 4 : g_conn_read_len = 0;
2426 : :
2427 : : /* SCSI Write PDU with immediate data */
2428 : 4 : scsi_reqh = (struct iscsi_bhs_scsi_req *)&pdu.bhs;
2429 : 4 : scsi_reqh->opcode = ISCSI_OP_SCSI;
2430 : 4 : scsi_reqh->write_bit = 1;
2431 : 4 : scsi_reqh->final_bit = 1;
2432 : 4 : pdu.data_segment_len = 5792;
2433 : 4 : to_be32(&scsi_reqh->expected_data_xfer_len, 65536);
2434 : :
2435 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2436 : 4 : CU_ASSERT(rc == 0);
2437 : :
2438 : 4 : primary = pdu.task;
2439 [ + + ]: 4 : SPDK_CU_ASSERT_FATAL(primary != NULL);
2440 : :
2441 : 4 : CU_ASSERT(primary->scsi.transfer_len == 65536);
2442 : 4 : CU_ASSERT(primary->scsi.dxfer_dir == SPDK_SCSI_DIR_TO_DEV);
2443 : 4 : CU_ASSERT(pdu.data_buf_len == 65536);
2444 : :
2445 : 4 : MOCK_SET(spdk_mempool_get, &mobj);
2446 : :
2447 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2448 : 4 : CU_ASSERT(rc == 0);
2449 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 0);
2450 : :
2451 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2452 : 4 : CU_ASSERT(rc == 0);
2453 : 4 : CU_ASSERT(primary->next_expected_r2t_offset == 5792);
2454 : 4 : CU_ASSERT(primary->current_r2t_length == 0);
2455 : 4 : CU_ASSERT(primary->next_r2t_offset == 65536);
2456 : 4 : CU_ASSERT(primary->ttt == 2);
2457 : 4 : CU_ASSERT(primary == TAILQ_FIRST(&conn.active_r2t_tasks));
2458 : :
2459 : 4 : check_pdu_payload_handle(&pdu, primary, NULL, NULL, &mobj, 0);
2460 : :
2461 : 4 : data_reqh = (struct iscsi_bhs_data_out *)&pdu.bhs;
2462 : :
2463 : : /* The 1st Data-OUT PDU */
2464 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2465 : 4 : data_reqh->opcode = ISCSI_OP_SCSI_DATAOUT;
2466 : 4 : to_be32(&data_reqh->ttt, 2);
2467 : 4 : to_be32(&data_reqh->buffer_offset, 5792);
2468 : 4 : pdu.data_segment_len = 15880;
2469 : :
2470 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2471 : 4 : CU_ASSERT(rc == 0);
2472 : 4 : check_pdu_hdr_handle(&pdu, &mobj, 5792, primary);
2473 : :
2474 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2475 : 4 : CU_ASSERT(rc == 0);
2476 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 5792);
2477 : :
2478 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2479 : 4 : CU_ASSERT(rc == 0);
2480 : 4 : check_pdu_payload_handle(&pdu, primary, NULL, NULL, &mobj, 0);
2481 : :
2482 : : /* The 2nd Data-OUT PDU */
2483 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2484 : 4 : data_reqh->opcode = ISCSI_OP_SCSI_DATAOUT;
2485 : 4 : to_be32(&data_reqh->ttt, 2);
2486 : 4 : to_be32(&data_reqh->buffer_offset, 21672);
2487 : 4 : to_be32(&data_reqh->data_sn, 1);
2488 : 4 : pdu.data_segment_len = 11536;
2489 : :
2490 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2491 : 4 : CU_ASSERT(rc == 0);
2492 : 4 : check_pdu_hdr_handle(&pdu, &mobj, 21672, primary);
2493 : :
2494 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2495 : 4 : CU_ASSERT(rc == 0);
2496 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 21672);
2497 : :
2498 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2499 : 4 : CU_ASSERT(rc == 0);
2500 : 4 : check_pdu_payload_handle(&pdu, primary, NULL, NULL, &mobj, 0);
2501 : :
2502 : : /* The 3rd Data-OUT PDU */
2503 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2504 : 4 : data_reqh->opcode = ISCSI_OP_SCSI_DATAOUT;
2505 : 4 : to_be32(&data_reqh->ttt, 2);
2506 : 4 : to_be32(&data_reqh->buffer_offset, 33208);
2507 : 4 : to_be32(&data_reqh->data_sn, 2);
2508 : 4 : pdu.data_segment_len = 2848;
2509 : :
2510 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2511 : 4 : CU_ASSERT(rc == 0);
2512 : 4 : check_pdu_hdr_handle(&pdu, &mobj, 33208, primary);
2513 : :
2514 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2515 : 4 : CU_ASSERT(rc == 0);
2516 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 33208);
2517 : :
2518 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2519 : 4 : CU_ASSERT(rc == 0);
2520 : 4 : check_pdu_payload_handle(&pdu, primary, NULL, NULL, &mobj, 0);
2521 : :
2522 : : /* The 4th Data-OUT PDU */
2523 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2524 : 4 : data_reqh->opcode = ISCSI_OP_SCSI_DATAOUT;
2525 : 4 : to_be32(&data_reqh->ttt, 2);
2526 : 4 : to_be32(&data_reqh->buffer_offset, 36056);
2527 : 4 : to_be32(&data_reqh->data_sn, 3);
2528 : 4 : pdu.data_segment_len = 11536;
2529 : :
2530 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2531 : 4 : CU_ASSERT(rc == 0);
2532 : 4 : check_pdu_hdr_handle(&pdu, &mobj, 36056, primary);
2533 : :
2534 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2535 : 4 : CU_ASSERT(rc == 0);
2536 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 36056);
2537 : :
2538 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2539 : 4 : CU_ASSERT(rc == 0);
2540 : 4 : check_pdu_payload_handle(&pdu, primary, NULL, NULL, &mobj, 0);
2541 : :
2542 : : /* The 5th Data-OUT PDU */
2543 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2544 : 4 : data_reqh->opcode = ISCSI_OP_SCSI_DATAOUT;
2545 : 4 : to_be32(&data_reqh->ttt, 2);
2546 : 4 : to_be32(&data_reqh->buffer_offset, 47592);
2547 : 4 : to_be32(&data_reqh->data_sn, 4);
2548 : 4 : pdu.data_segment_len = 5744;
2549 : :
2550 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2551 : 4 : CU_ASSERT(rc == 0);
2552 : 4 : check_pdu_hdr_handle(&pdu, &mobj, 47592, primary);
2553 : :
2554 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2555 : 4 : CU_ASSERT(rc == 0);
2556 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 47592);
2557 : :
2558 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2559 : 4 : CU_ASSERT(rc == 0);
2560 : 4 : check_pdu_payload_handle(&pdu, primary, NULL, NULL, &mobj, 0);
2561 : :
2562 : : /* The 6th and final Data-OUT PDU */
2563 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
2564 : 4 : pdu.bhs.opcode = ISCSI_OP_SCSI_DATAOUT;
2565 : 4 : data_reqh->flags |= ISCSI_FLAG_FINAL;
2566 : 4 : to_be32(&data_reqh->ttt, 2);
2567 : 4 : to_be32(&data_reqh->buffer_offset, 53336);
2568 : 4 : to_be32(&data_reqh->data_sn, 5);
2569 : 4 : pdu.data_segment_len = 12200;
2570 : :
2571 : 4 : rc = iscsi_pdu_hdr_handle(&conn, &pdu);
2572 : 4 : CU_ASSERT(rc == 0);
2573 : 4 : check_pdu_hdr_handle(&pdu, &mobj, 53336, primary);
2574 : :
2575 : 4 : rc = iscsi_pdu_payload_read(&conn, &pdu);
2576 : 4 : CU_ASSERT(rc == 0);
2577 : 4 : check_pdu_payload_read(&pdu, &mobj, rc, 0, 53336);
2578 : :
2579 : 4 : rc = iscsi_pdu_payload_handle(&conn, &pdu);
2580 : 4 : CU_ASSERT(rc == 0);
2581 : 4 : check_pdu_payload_handle(&pdu, primary, &mobj, NULL, NULL, 65536);
2582 : :
2583 : 4 : check_write_subtask_submit(&lun, &mobj, &pdu, 0, 0, 65536);
2584 : :
2585 : 4 : CU_ASSERT(TAILQ_EMPTY(&lun.tasks));
2586 : :
2587 [ - + - + ]: 4 : MOCK_CLEAR(spdk_mempool_get);
2588 : :
2589 : 4 : free(primary);
2590 : 4 : free(mobj.buf);
2591 : 4 : }
2592 : :
2593 : : int
2594 : 4 : main(int argc, char **argv)
2595 : : {
2596 : 4 : CU_pSuite suite = NULL;
2597 : : unsigned int num_failures;
2598 : :
2599 : 4 : CU_initialize_registry();
2600 : :
2601 : 4 : suite = CU_add_suite("iscsi_suite", NULL, NULL);
2602 : :
2603 : 4 : CU_ADD_TEST(suite, op_login_check_target_test);
2604 : 4 : CU_ADD_TEST(suite, op_login_session_normal_test);
2605 : 4 : CU_ADD_TEST(suite, maxburstlength_test);
2606 : 4 : CU_ADD_TEST(suite, underflow_for_read_transfer_test);
2607 : 4 : CU_ADD_TEST(suite, underflow_for_zero_read_transfer_test);
2608 : 4 : CU_ADD_TEST(suite, underflow_for_request_sense_test);
2609 : 4 : CU_ADD_TEST(suite, underflow_for_check_condition_test);
2610 : 4 : CU_ADD_TEST(suite, add_transfer_task_test);
2611 : 4 : CU_ADD_TEST(suite, get_transfer_task_test);
2612 : 4 : CU_ADD_TEST(suite, del_transfer_task_test);
2613 : 4 : CU_ADD_TEST(suite, clear_all_transfer_tasks_test);
2614 : 4 : CU_ADD_TEST(suite, build_iovs_test);
2615 : 4 : CU_ADD_TEST(suite, build_iovs_with_md_test);
2616 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_login_test);
2617 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_text_test);
2618 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_logout_test);
2619 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_scsi_test);
2620 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_task_mgmt_test);
2621 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_nopout_test);
2622 : 4 : CU_ADD_TEST(suite, pdu_hdr_op_data_test);
2623 : 4 : CU_ADD_TEST(suite, empty_text_with_cbit_test);
2624 : 4 : CU_ADD_TEST(suite, pdu_payload_read_test);
2625 : 4 : CU_ADD_TEST(suite, data_out_pdu_sequence_test);
2626 : 4 : CU_ADD_TEST(suite, immediate_data_and_data_out_pdu_sequence_test);
2627 : :
2628 : 4 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
2629 : 4 : CU_cleanup_registry();
2630 : 4 : return num_failures;
2631 : : }
|