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