4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5 * Copyright (c) Intel Corporation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "spdk/stdinc.h"
37 #include "spdk/base64.h"
38 #include "spdk/crc32.h"
39 #include "spdk/endian.h"
41 #include "spdk/likely.h"
42 #include "spdk/trace.h"
43 #include "spdk/string.h"
44 #include "spdk/queue.h"
47 #include "iscsi/md5.h"
48 #include "iscsi/iscsi.h"
49 #include "iscsi/param.h"
50 #include "iscsi/tgt_node.h"
51 #include "iscsi/task.h"
52 #include "iscsi/conn.h"
53 #include "spdk/scsi.h"
54 #include "spdk/bdev.h"
55 #include "iscsi/portal_grp.h"
57 #include "spdk_internal/log.h"
59 #define MAX_TMPBUF 1024
61 #define SPDK_CRC32C_INITIAL 0xffffffffUL
62 #define SPDK_CRC32C_XOR 0xffffffffUL
65 #define HAVE_SRANDOMDEV 1
66 #define HAVE_ARC4RANDOM 1
69 struct spdk_iscsi_globals g_spdk_iscsi
= {
70 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
71 .portal_head
= TAILQ_HEAD_INITIALIZER(g_spdk_iscsi
.portal_head
),
72 .pg_head
= TAILQ_HEAD_INITIALIZER(g_spdk_iscsi
.pg_head
),
73 .ig_head
= TAILQ_HEAD_INITIALIZER(g_spdk_iscsi
.ig_head
),
74 .target_head
= TAILQ_HEAD_INITIALIZER(g_spdk_iscsi
.target_head
),
75 .auth_group_head
= TAILQ_HEAD_INITIALIZER(g_spdk_iscsi
.auth_group_head
),
78 /* random value generation */
79 static void gen_random(uint8_t *buf
, size_t len
);
80 #ifndef HAVE_SRANDOMDEV
81 static void srandomdev(void);
82 #endif /* HAVE_SRANDOMDEV */
83 #ifndef HAVE_ARC4RANDOM
84 /* static uint32_t arc4random(void); */
85 #endif /* HAVE_ARC4RANDOM */
87 static int add_transfer_task(struct spdk_iscsi_conn
*conn
,
88 struct spdk_iscsi_task
*task
);
90 static int iscsi_send_r2t(struct spdk_iscsi_conn
*conn
,
91 struct spdk_iscsi_task
*task
, int offset
,
92 int len
, uint32_t transfer_tag
, uint32_t *R2TSN
);
93 static int iscsi_send_r2t_recovery(struct spdk_iscsi_conn
*conn
,
94 struct spdk_iscsi_task
*r2t_task
, uint32_t r2t_sn
,
97 static int create_iscsi_sess(struct spdk_iscsi_conn
*conn
,
98 struct spdk_iscsi_tgt_node
*target
, enum session_type session_type
);
99 static uint8_t append_iscsi_sess(struct spdk_iscsi_conn
*conn
,
100 const char *initiator_port_name
, uint16_t tsih
, uint16_t cid
);
102 static void remove_acked_pdu(struct spdk_iscsi_conn
*conn
, uint32_t ExpStatSN
);
104 static int iscsi_reject(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
,
107 #define DMIN32(A,B) ((uint32_t) ((uint32_t)(A) > (uint32_t)(B) ? (uint32_t)(B) : (uint32_t)(A)))
108 #define DMIN64(A,B) ((uint64_t) ((A) > (B) ? (B) : (A)))
110 #define MATCH_DIGEST_WORD(BUF, CRC32C) \
111 ( ((((uint32_t) *((uint8_t *)(BUF)+0)) << 0) \
112 | (((uint32_t) *((uint8_t *)(BUF)+1)) << 8) \
113 | (((uint32_t) *((uint8_t *)(BUF)+2)) << 16) \
114 | (((uint32_t) *((uint8_t *)(BUF)+3)) << 24)) \
119 match_digest_word(const uint8_t *buf
, uint32_t crc32c
)
123 l
= (buf
[0] & 0xffU
) << 0;
124 l
|= (buf
[1] & 0xffU
) << 8;
125 l
|= (buf
[2] & 0xffU
) << 16;
126 l
|= (buf
[3] & 0xffU
) << 24;
127 return (l
== crc32c
);
131 make_digest_word(uint8_t *buf
, size_t len
, uint32_t crc32c
)
133 if (len
< ISCSI_DIGEST_LEN
) {
137 buf
[0] = (crc32c
>> 0) & 0xffU
;
138 buf
[1] = (crc32c
>> 8) & 0xffU
;
139 buf
[2] = (crc32c
>> 16) & 0xffU
;
140 buf
[3] = (crc32c
>> 24) & 0xffU
;
145 #ifndef HAVE_SRANDOMDEV
158 #endif /* HAVE_SRANDOMDEV */
160 #ifndef HAVE_ARC4RANDOM
161 static int g_arc4random_initialized
= 0;
169 if (!g_arc4random_initialized
) {
171 g_arc4random_initialized
= 1;
173 r1
= (uint32_t)(random() & 0xffff);
174 r2
= (uint32_t)(random() & 0xffff);
178 #endif /* HAVE_ARC4RANDOM */
181 gen_random(uint8_t *buf
, size_t len
)
188 for (idx
= 0; idx
< len
; idx
++) {
190 buf
[idx
] = (uint8_t) l
;
196 for (idx
= 0; idx
< len
; idx
++) {
198 buf
[idx
] = (uint8_t) r
;
200 #endif /* USE_RANDOM */
204 iscsi_get_isid(const uint8_t isid
[6])
206 return (uint64_t)isid
[0] << 40 |
207 (uint64_t)isid
[1] << 32 |
208 (uint64_t)isid
[2] << 24 |
209 (uint64_t)isid
[3] << 16 |
210 (uint64_t)isid
[4] << 8 |
215 bin2hex(char *buf
, size_t len
, const uint8_t *data
, size_t data_len
)
217 const char *digits
= "0123456789ABCDEF";
230 for (idx
= 0; idx
< data_len
; idx
++) {
231 if (total
+ 3 > len
) {
235 buf
[total
] = digits
[(data
[idx
] >> 4) & 0x0fU
];
237 buf
[total
] = digits
[data
[idx
] & 0x0fU
];
245 hex2bin(uint8_t *data
, size_t data_len
, const char *str
)
247 const char *digits
= "0123456789ABCDEF";
254 if (p
[0] != '0' && (p
[1] != 'x' && p
[1] != 'X')) {
259 while (p
[0] != '\0' && p
[1] != '\0') {
260 if (total
>= data_len
) {
263 dp
= strchr(digits
, toupper((int) p
[0]));
267 n0
= (int)(dp
- digits
);
268 dp
= strchr(digits
, toupper((int) p
[1]));
272 n1
= (int)(dp
- digits
);
274 data
[total
] = (uint8_t)(((n0
& 0x0fU
) << 4) | (n1
& 0x0fU
));
282 spdk_iscsi_pdu_calc_header_digest(struct spdk_iscsi_pdu
*pdu
)
285 uint32_t ahs_len_bytes
= pdu
->bhs
.total_ahs_len
* 4;
287 crc32c
= SPDK_CRC32C_INITIAL
;
288 crc32c
= spdk_crc32c_update(&pdu
->bhs
, ISCSI_BHS_LEN
, crc32c
);
291 crc32c
= spdk_crc32c_update(pdu
->ahs
, ahs_len_bytes
, crc32c
);
294 /* BHS and AHS are always 4-byte multiples in length, so no padding is necessary. */
295 crc32c
= crc32c
^ SPDK_CRC32C_XOR
;
300 spdk_iscsi_pdu_calc_data_digest(struct spdk_iscsi_pdu
*pdu
)
302 uint32_t data_len
= DGET24(pdu
->bhs
.data_segment_len
);
308 crc32c
= SPDK_CRC32C_INITIAL
;
309 if (spdk_likely(!pdu
->dif_insert_or_strip
)) {
310 crc32c
= spdk_crc32c_update(pdu
->data
, data_len
, crc32c
);
312 iov
.iov_base
= pdu
->data_buf
;
313 iov
.iov_len
= pdu
->data_buf_len
;
314 num_blocks
= pdu
->data_buf_len
/ pdu
->dif_ctx
.block_size
;
316 spdk_dif_update_crc32c(&iov
, 1, num_blocks
, &crc32c
, &pdu
->dif_ctx
);
319 mod
= data_len
% ISCSI_ALIGNMENT
;
321 uint32_t pad_length
= ISCSI_ALIGNMENT
- mod
;
322 uint8_t pad
[3] = {0, 0, 0};
324 assert(pad_length
> 0);
325 assert(pad_length
<= sizeof(pad
));
326 crc32c
= spdk_crc32c_update(pad
, pad_length
, crc32c
);
329 crc32c
= crc32c
^ SPDK_CRC32C_XOR
;
334 iscsi_check_data_segment_length(struct spdk_iscsi_conn
*conn
,
335 struct spdk_iscsi_pdu
*pdu
, int data_len
)
340 * Determine the maximum segment length expected for this PDU.
341 * This will be used to make sure the initiator did not send
342 * us too much immediate data.
344 * This value is specified separately by the initiator and target,
345 * and not negotiated. So we can use the #define safely here,
346 * since the value is not dependent on the initiator's maximum
347 * segment lengths (FirstBurstLength/MaxRecvDataSegmentLength),
348 * and SPDK currently does not allow configuration of these values
351 if (conn
->sess
== NULL
) {
353 * If the connection does not yet have a session, then
354 * login is not complete and we use the 8KB default
355 * FirstBurstLength as our maximum data segment length
358 max_segment_len
= SPDK_ISCSI_FIRST_BURST_LENGTH
;
359 } else if (pdu
->bhs
.opcode
== ISCSI_OP_SCSI_DATAOUT
||
360 pdu
->bhs
.opcode
== ISCSI_OP_NOPOUT
) {
361 max_segment_len
= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
;
363 max_segment_len
= spdk_get_max_immediate_data_size();
365 if (data_len
<= max_segment_len
) {
368 SPDK_ERRLOG("Data(%d) > MaxSegment(%d)\n", data_len
, max_segment_len
);
374 iscsi_conn_read_data_segment(struct spdk_iscsi_conn
*conn
,
375 struct spdk_iscsi_pdu
*pdu
,
376 uint32_t segment_len
)
378 struct iovec buf_iov
, iovs
[32];
381 if (spdk_likely(!pdu
->dif_insert_or_strip
)) {
382 return spdk_iscsi_conn_read_data(conn
,
383 segment_len
- pdu
->data_valid_bytes
,
384 pdu
->data_buf
+ pdu
->data_valid_bytes
);
386 buf_iov
.iov_base
= pdu
->data_buf
;
387 buf_iov
.iov_len
= pdu
->data_buf_len
;
388 rc
= spdk_dif_set_md_interleave_iovs(iovs
, 32, &buf_iov
, 1,
389 pdu
->data_valid_bytes
, segment_len
, NULL
,
392 rc
= spdk_iscsi_conn_readv_data(conn
, iovs
, rc
);
394 _rc
= spdk_dif_generate_stream(&buf_iov
, 1,
395 pdu
->data_valid_bytes
, rc
,
398 SPDK_ERRLOG("DIF generate failed\n");
403 SPDK_ERRLOG("Setup iovs for interleaved metadata failed\n");
410 spdk_iscsi_read_pdu(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
**_pdu
)
412 struct spdk_iscsi_pdu
*pdu
;
413 struct spdk_mempool
*pool
;
419 if (conn
->pdu_in_progress
== NULL
) {
420 conn
->pdu_in_progress
= spdk_get_pdu();
421 if (conn
->pdu_in_progress
== NULL
) {
422 return SPDK_ISCSI_CONNECTION_FATAL
;
426 pdu
= conn
->pdu_in_progress
;
428 if (pdu
->bhs_valid_bytes
< ISCSI_BHS_LEN
) {
429 rc
= spdk_iscsi_conn_read_data(conn
,
430 ISCSI_BHS_LEN
- pdu
->bhs_valid_bytes
,
431 (uint8_t *)&pdu
->bhs
+ pdu
->bhs_valid_bytes
);
435 pdu
->bhs_valid_bytes
+= rc
;
436 if (pdu
->bhs_valid_bytes
< ISCSI_BHS_LEN
) {
441 data_len
= ISCSI_ALIGN(DGET24(pdu
->bhs
.data_segment_len
));
444 ahs_len
= pdu
->bhs
.total_ahs_len
* 4;
445 assert(ahs_len
<= ISCSI_AHS_LEN
);
446 if (pdu
->ahs_valid_bytes
< ahs_len
) {
447 rc
= spdk_iscsi_conn_read_data(conn
,
448 ahs_len
- pdu
->ahs_valid_bytes
,
449 pdu
->ahs
+ pdu
->ahs_valid_bytes
);
454 pdu
->ahs_valid_bytes
+= rc
;
455 if (pdu
->ahs_valid_bytes
< ahs_len
) {
461 if (conn
->header_digest
&&
462 pdu
->hdigest_valid_bytes
< ISCSI_DIGEST_LEN
) {
463 rc
= spdk_iscsi_conn_read_data(conn
,
464 ISCSI_DIGEST_LEN
- pdu
->hdigest_valid_bytes
,
465 pdu
->header_digest
+ pdu
->hdigest_valid_bytes
);
470 pdu
->hdigest_valid_bytes
+= rc
;
471 if (pdu
->hdigest_valid_bytes
< ISCSI_DIGEST_LEN
) {
476 /* copy the actual data into local buffer */
477 if (pdu
->data_valid_bytes
< data_len
) {
478 if (pdu
->data_buf
== NULL
) {
479 if (data_len
<= spdk_get_max_immediate_data_size()) {
480 pool
= g_spdk_iscsi
.pdu_immediate_data_pool
;
481 pdu
->data_buf_len
= SPDK_BDEV_BUF_SIZE_WITH_MD(spdk_get_max_immediate_data_size());
482 } else if (data_len
<= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
) {
483 pool
= g_spdk_iscsi
.pdu_data_out_pool
;
484 pdu
->data_buf_len
= SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
);
486 SPDK_ERRLOG("Data(%d) > MaxSegment(%d)\n",
487 data_len
, SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
);
490 pdu
->mobj
= spdk_mempool_get(pool
);
491 if (pdu
->mobj
== NULL
) {
494 pdu
->data_buf
= pdu
->mobj
->buf
;
496 if (spdk_unlikely(spdk_iscsi_get_dif_ctx(conn
, pdu
, &pdu
->dif_ctx
))) {
497 pdu
->dif_insert_or_strip
= true;
501 rc
= iscsi_conn_read_data_segment(conn
, pdu
, data_len
);
506 pdu
->data_valid_bytes
+= rc
;
507 if (pdu
->data_valid_bytes
< data_len
) {
512 /* copy out the data digest */
513 if (conn
->data_digest
&& data_len
!= 0 &&
514 pdu
->ddigest_valid_bytes
< ISCSI_DIGEST_LEN
) {
515 rc
= spdk_iscsi_conn_read_data(conn
,
516 ISCSI_DIGEST_LEN
- pdu
->ddigest_valid_bytes
,
517 pdu
->data_digest
+ pdu
->ddigest_valid_bytes
);
522 pdu
->ddigest_valid_bytes
+= rc
;
523 if (pdu
->ddigest_valid_bytes
< ISCSI_DIGEST_LEN
) {
528 /* All data for this PDU has now been read from the socket. */
529 conn
->pdu_in_progress
= NULL
;
531 spdk_trace_record(TRACE_ISCSI_READ_PDU
, conn
->id
, pdu
->data_valid_bytes
,
532 (uintptr_t)pdu
, pdu
->bhs
.opcode
);
536 if (!iscsi_check_data_segment_length(conn
, pdu
, data_len
)) {
537 rc
= iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
539 * If spdk_iscsi_reject() was not able to reject the PDU,
540 * treat it as a fatal connection error. Otherwise,
541 * return SUCCESS here so that the caller will continue
542 * to attempt to read PDUs.
552 pdu
->data
= pdu
->data_buf
;
553 pdu
->data_from_mempool
= true;
554 pdu
->data_segment_len
= data_len
;
558 if (conn
->header_digest
) {
559 crc32c
= spdk_iscsi_pdu_calc_header_digest(pdu
);
560 rc
= MATCH_DIGEST_WORD(pdu
->header_digest
, crc32c
);
562 SPDK_ERRLOG("header digest error (%s)\n", conn
->initiator_name
);
566 if (conn
->data_digest
&& data_len
!= 0) {
567 crc32c
= spdk_iscsi_pdu_calc_data_digest(pdu
);
568 rc
= MATCH_DIGEST_WORD(pdu
->data_digest
, crc32c
);
570 SPDK_ERRLOG("data digest error (%s)\n", conn
->initiator_name
);
580 conn
->pdu_in_progress
= NULL
;
581 return SPDK_ISCSI_CONNECTION_FATAL
;
592 _iscsi_sgl_init(struct _iscsi_sgl
*s
, struct iovec
*iovs
, int iovcnt
,
597 s
->iov_offset
= iov_offset
;
602 _iscsi_sgl_append(struct _iscsi_sgl
*s
, uint8_t *data
, uint32_t data_len
)
604 if (s
->iov_offset
>= data_len
) {
605 s
->iov_offset
-= data_len
;
607 assert(s
->iovcnt
> 0);
608 s
->iov
->iov_base
= data
+ s
->iov_offset
;
609 s
->iov
->iov_len
= data_len
- s
->iov_offset
;
610 s
->total_size
+= data_len
- s
->iov_offset
;
614 if (s
->iovcnt
== 0) {
622 /* Build iovec array to leave metadata space for every data block
623 * when reading data segment from socket.
626 _iscsi_sgl_append_with_md(struct _iscsi_sgl
*s
,
627 void *buf
, uint32_t buf_len
, uint32_t data_len
,
628 struct spdk_dif_ctx
*dif_ctx
)
631 uint32_t total_size
= 0;
632 struct iovec buf_iov
;
634 if (s
->iov_offset
>= data_len
) {
635 s
->iov_offset
-= buf_len
;
637 buf_iov
.iov_base
= buf
;
638 buf_iov
.iov_len
= buf_len
;
639 rc
= spdk_dif_set_md_interleave_iovs(s
->iov
, s
->iovcnt
, &buf_iov
, 1,
640 s
->iov_offset
, data_len
, &total_size
,
643 SPDK_ERRLOG("Failed to setup iovs for DIF strip\n");
647 s
->total_size
+= total_size
;
649 assert(s
->iovcnt
>= rc
);
653 if (s
->iovcnt
== 0) {
662 spdk_iscsi_build_iovs(struct spdk_iscsi_conn
*conn
, struct iovec
*iovs
, int iovcnt
,
663 struct spdk_iscsi_pdu
*pdu
, uint32_t *_mapped_length
)
665 struct _iscsi_sgl sgl
;
667 uint32_t total_ahs_len
;
674 total_ahs_len
= pdu
->bhs
.total_ahs_len
;
675 data_len
= DGET24(pdu
->bhs
.data_segment_len
);
676 data_len
= ISCSI_ALIGN(data_len
);
679 if (pdu
->bhs
.opcode
== ISCSI_OP_LOGIN_RSP
) {
680 /* this PDU should be sent without digest */
684 _iscsi_sgl_init(&sgl
, iovs
, iovcnt
, pdu
->writev_offset
);
687 if (!_iscsi_sgl_append(&sgl
, (uint8_t *)&pdu
->bhs
, ISCSI_BHS_LEN
)) {
691 if (total_ahs_len
> 0) {
692 if (!_iscsi_sgl_append(&sgl
, pdu
->ahs
, 4 * total_ahs_len
)) {
698 if (enable_digest
&& conn
->header_digest
) {
699 if (!_iscsi_sgl_append(&sgl
, pdu
->header_digest
, ISCSI_DIGEST_LEN
)) {
706 if (!pdu
->dif_insert_or_strip
) {
707 if (!_iscsi_sgl_append(&sgl
, pdu
->data
, data_len
)) {
711 if (!_iscsi_sgl_append_with_md(&sgl
, pdu
->data
, pdu
->data_buf_len
,
712 data_len
, &pdu
->dif_ctx
)) {
719 if (enable_digest
&& conn
->data_digest
&& data_len
!= 0) {
720 _iscsi_sgl_append(&sgl
, pdu
->data_digest
, ISCSI_DIGEST_LEN
);
724 if (_mapped_length
!= NULL
) {
725 *_mapped_length
= sgl
.total_size
;
728 return iovcnt
- sgl
.iovcnt
;
732 iscsi_append_text(struct spdk_iscsi_conn
*conn
__attribute__((__unused__
)),
733 const char *key
, const char *val
, uint8_t *data
,
734 int alloc_len
, int data_len
)
743 if (total
> alloc_len
) {
745 data
[total
- 1] = '\0';
749 if (alloc_len
- total
< 1) {
750 SPDK_ERRLOG("data space small %d\n", alloc_len
);
753 len
= snprintf((char *) data
+ total
, alloc_len
- total
, "%s=%s", key
, val
);
760 iscsi_append_param(struct spdk_iscsi_conn
*conn
, const char *key
,
761 uint8_t *data
, int alloc_len
, int data_len
)
763 struct iscsi_param
*param
;
766 param
= spdk_iscsi_param_find(conn
->params
, key
);
768 param
= spdk_iscsi_param_find(conn
->sess
->params
, key
);
770 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "no key %.64s\n", key
);
774 rc
= iscsi_append_text(conn
, param
->key
, param
->val
, data
,
775 alloc_len
, data_len
);
780 iscsi_get_authinfo(struct spdk_iscsi_conn
*conn
, const char *authuser
)
785 if (conn
->sess
->target
!= NULL
) {
786 ag_tag
= conn
->sess
->target
->chap_group
;
791 ag_tag
= g_spdk_iscsi
.chap_group
;
793 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "ag_tag=%d\n", ag_tag
);
795 rc
= spdk_iscsi_chap_get_authinfo(&conn
->auth
, authuser
, ag_tag
);
797 SPDK_ERRLOG("chap_get_authinfo() failed\n");
804 iscsi_auth_params(struct spdk_iscsi_conn
*conn
,
805 struct iscsi_param
*params
, const char *method
, uint8_t *data
,
806 int alloc_len
, int data_len
)
811 const char *algorithm
;
813 const char *response
;
814 const char *identifier
;
815 const char *challenge
;
819 if (conn
== NULL
|| params
== NULL
|| method
== NULL
) {
822 if (strcasecmp(method
, "CHAP") == 0) {
825 SPDK_ERRLOG("unsupported AuthMethod %.64s\n", method
);
833 if (total
> alloc_len
) {
835 data
[total
- 1] = '\0';
839 /* for temporary store */
840 in_val
= malloc(ISCSI_TEXT_MAX_VAL_LEN
+ 1);
842 SPDK_ERRLOG("malloc() failed for temporary store\n");
846 /* CHAP method (RFC1994) */
847 if ((algorithm
= spdk_iscsi_param_get_val(params
, "CHAP_A")) != NULL
) {
848 if (conn
->auth
.chap_phase
!= ISCSI_CHAP_PHASE_WAIT_A
) {
849 SPDK_ERRLOG("CHAP sequence error\n");
853 /* CHAP_A is LIST type */
854 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", algorithm
);
856 while ((new_val
= spdk_strsepq(&in_next
, ",")) != NULL
) {
857 if (strcasecmp(new_val
, "5") == 0) {
862 if (new_val
== NULL
) {
863 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
+ 1, "%s", "Reject");
865 iscsi_append_text(conn
, "CHAP_A", new_val
,
866 data
, alloc_len
, total
);
869 /* selected algorithm is 5 (MD5) */
870 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "got CHAP_A=%s\n", new_val
);
871 total
= iscsi_append_text(conn
, "CHAP_A", new_val
,
872 data
, alloc_len
, total
);
874 /* Identifier is one octet */
875 gen_random(conn
->auth
.chap_id
, 1);
876 snprintf(in_val
, ISCSI_TEXT_MAX_VAL_LEN
, "%d",
877 (int) conn
->auth
.chap_id
[0]);
878 total
= iscsi_append_text(conn
, "CHAP_I", in_val
,
879 data
, alloc_len
, total
);
881 /* Challenge Value is a variable stream of octets */
882 /* (binary length MUST not exceed 1024 bytes) */
883 conn
->auth
.chap_challenge_len
= ISCSI_CHAP_CHALLENGE_LEN
;
884 gen_random(conn
->auth
.chap_challenge
, conn
->auth
.chap_challenge_len
);
885 bin2hex(in_val
, ISCSI_TEXT_MAX_VAL_LEN
,
886 conn
->auth
.chap_challenge
, conn
->auth
.chap_challenge_len
);
887 total
= iscsi_append_text(conn
, "CHAP_C", in_val
,
888 data
, alloc_len
, total
);
890 conn
->auth
.chap_phase
= ISCSI_CHAP_PHASE_WAIT_NR
;
891 } else if ((name
= spdk_iscsi_param_get_val(params
, "CHAP_N")) != NULL
) {
892 uint8_t resmd5
[SPDK_MD5DIGEST_LEN
];
893 uint8_t tgtmd5
[SPDK_MD5DIGEST_LEN
];
894 struct spdk_md5ctx md5ctx
;
895 size_t decoded_len
= 0;
897 if (conn
->auth
.chap_phase
!= ISCSI_CHAP_PHASE_WAIT_NR
) {
898 SPDK_ERRLOG("CHAP sequence error\n");
902 response
= spdk_iscsi_param_get_val(params
, "CHAP_R");
903 if (response
== NULL
) {
904 SPDK_ERRLOG("no response\n");
907 if (response
[0] == '0' &&
908 (response
[1] == 'x' || response
[1] == 'X')) {
909 rc
= hex2bin(resmd5
, SPDK_MD5DIGEST_LEN
, response
);
910 if (rc
< 0 || rc
!= SPDK_MD5DIGEST_LEN
) {
911 SPDK_ERRLOG("response format error\n");
914 } else if (response
[0] == '0' &&
915 (response
[1] == 'b' || response
[1] == 'B')) {
917 rc
= spdk_base64_decode(resmd5
, &decoded_len
, response
);
918 if (rc
< 0 || decoded_len
!= SPDK_MD5DIGEST_LEN
) {
919 SPDK_ERRLOG("response format error\n");
923 SPDK_ERRLOG("response format error\n");
926 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "got CHAP_N/CHAP_R\n");
928 rc
= iscsi_get_authinfo(conn
, name
);
930 /* SPDK_ERRLOG("auth user or secret is missing\n"); */
931 SPDK_ERRLOG("iscsi_get_authinfo() failed\n");
934 if (conn
->auth
.user
[0] == '\0' || conn
->auth
.secret
[0] == '\0') {
935 /* SPDK_ERRLOG("auth user or secret is missing\n"); */
936 SPDK_ERRLOG("auth failed (name %.64s)\n", name
);
940 spdk_md5init(&md5ctx
);
942 spdk_md5update(&md5ctx
, conn
->auth
.chap_id
, 1);
943 /* followed by secret */
944 spdk_md5update(&md5ctx
, conn
->auth
.secret
,
945 strlen(conn
->auth
.secret
));
946 /* followed by Challenge Value */
947 spdk_md5update(&md5ctx
, conn
->auth
.chap_challenge
,
948 conn
->auth
.chap_challenge_len
);
949 /* tgtmd5 is expecting Response Value */
950 spdk_md5final(tgtmd5
, &md5ctx
);
952 bin2hex(in_val
, ISCSI_TEXT_MAX_VAL_LEN
, tgtmd5
, SPDK_MD5DIGEST_LEN
);
955 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "tgtmd5=%s, resmd5=%s\n", in_val
, response
);
956 spdk_dump("tgtmd5", tgtmd5
, SPDK_MD5DIGEST_LEN
);
957 spdk_dump("resmd5", resmd5
, SPDK_MD5DIGEST_LEN
);
960 /* compare MD5 digest */
961 if (memcmp(tgtmd5
, resmd5
, SPDK_MD5DIGEST_LEN
) != 0) {
963 /* SPDK_ERRLOG("auth user or secret is missing\n"); */
964 SPDK_ERRLOG("auth failed (name %.64s)\n", name
);
967 /* OK initiator's secret */
968 conn
->authenticated
= true;
971 identifier
= spdk_iscsi_param_get_val(params
, "CHAP_I");
972 if (identifier
!= NULL
) {
973 conn
->auth
.chap_mid
[0] = (uint8_t) strtol(identifier
, NULL
, 10);
974 challenge
= spdk_iscsi_param_get_val(params
, "CHAP_C");
975 if (challenge
== NULL
) {
976 SPDK_ERRLOG("CHAP sequence error\n");
979 if (challenge
[0] == '0' &&
980 (challenge
[1] == 'x' || challenge
[1] == 'X')) {
981 rc
= hex2bin(conn
->auth
.chap_mchallenge
,
982 ISCSI_CHAP_CHALLENGE_LEN
, challenge
);
984 SPDK_ERRLOG("challenge format error\n");
987 conn
->auth
.chap_mchallenge_len
= rc
;
988 } else if (challenge
[0] == '0' &&
989 (challenge
[1] == 'b' || challenge
[1] == 'B')) {
991 rc
= spdk_base64_decode(conn
->auth
.chap_mchallenge
,
992 &decoded_len
, challenge
);
994 SPDK_ERRLOG("challenge format error\n");
997 conn
->auth
.chap_mchallenge_len
= decoded_len
;
999 SPDK_ERRLOG("challenge format error\n");
1003 spdk_dump("MChallenge", conn
->auth
.chap_mchallenge
,
1004 conn
->auth
.chap_mchallenge_len
);
1006 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "got CHAP_I/CHAP_C\n");
1008 if (conn
->auth
.muser
[0] == '\0' || conn
->auth
.msecret
[0] == '\0') {
1009 /* SPDK_ERRLOG("mutual auth user or secret is missing\n"); */
1010 SPDK_ERRLOG("auth failed (name %.64s)\n", name
);
1014 spdk_md5init(&md5ctx
);
1016 spdk_md5update(&md5ctx
, conn
->auth
.chap_mid
, 1);
1017 /* followed by secret */
1018 spdk_md5update(&md5ctx
, conn
->auth
.msecret
,
1019 strlen(conn
->auth
.msecret
));
1020 /* followed by Challenge Value */
1021 spdk_md5update(&md5ctx
, conn
->auth
.chap_mchallenge
,
1022 conn
->auth
.chap_mchallenge_len
);
1023 /* tgtmd5 is Response Value */
1024 spdk_md5final(tgtmd5
, &md5ctx
);
1026 bin2hex(in_val
, ISCSI_TEXT_MAX_VAL_LEN
, tgtmd5
, SPDK_MD5DIGEST_LEN
);
1028 total
= iscsi_append_text(conn
, "CHAP_N",
1029 conn
->auth
.muser
, data
, alloc_len
, total
);
1030 total
= iscsi_append_text(conn
, "CHAP_R",
1031 in_val
, data
, alloc_len
, total
);
1034 if (conn
->mutual_chap
) {
1035 SPDK_ERRLOG("required mutual CHAP\n");
1040 conn
->auth
.chap_phase
= ISCSI_CHAP_PHASE_END
;
1042 /* not found CHAP keys */
1043 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "start CHAP\n");
1044 conn
->auth
.chap_phase
= ISCSI_CHAP_PHASE_WAIT_A
;
1051 conn
->auth
.chap_phase
= ISCSI_CHAP_PHASE_WAIT_A
;
1057 iscsi_reject(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
,
1060 struct spdk_iscsi_pdu
*rsp_pdu
;
1061 struct iscsi_bhs_reject
*rsph
;
1067 total_ahs_len
= pdu
->bhs
.total_ahs_len
;
1069 alloc_len
= ISCSI_BHS_LEN
+ (4 * total_ahs_len
);
1071 if (conn
->header_digest
) {
1072 alloc_len
+= ISCSI_DIGEST_LEN
;
1075 data
= calloc(1, alloc_len
);
1077 SPDK_ERRLOG("calloc() failed for data segment\n");
1081 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Reject PDU reason=%d\n", reason
);
1083 if (conn
->sess
!= NULL
) {
1084 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
1085 "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
1086 conn
->StatSN
, conn
->sess
->ExpCmdSN
,
1087 conn
->sess
->MaxCmdSN
);
1089 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN=%u\n", conn
->StatSN
);
1092 memcpy(data
, &pdu
->bhs
, ISCSI_BHS_LEN
);
1093 data_len
+= ISCSI_BHS_LEN
;
1095 if (total_ahs_len
!= 0) {
1096 memcpy(data
+ data_len
, pdu
->ahs
, (4 * total_ahs_len
));
1097 data_len
+= (4 * total_ahs_len
);
1100 if (conn
->header_digest
) {
1101 memcpy(data
+ data_len
, pdu
->header_digest
, ISCSI_DIGEST_LEN
);
1102 data_len
+= ISCSI_DIGEST_LEN
;
1105 rsp_pdu
= spdk_get_pdu();
1106 if (rsp_pdu
== NULL
) {
1111 rsph
= (struct iscsi_bhs_reject
*)&rsp_pdu
->bhs
;
1112 rsp_pdu
->data
= data
;
1113 rsph
->opcode
= ISCSI_OP_REJECT
;
1114 rsph
->flags
|= 0x80; /* bit 0 is default to 1 */
1115 rsph
->reason
= reason
;
1116 DSET24(rsph
->data_segment_len
, data_len
);
1118 rsph
->ffffffff
= 0xffffffffU
;
1119 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
1122 if (conn
->sess
!= NULL
) {
1123 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
1124 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
1126 to_be32(&rsph
->exp_cmd_sn
, 1);
1127 to_be32(&rsph
->max_cmd_sn
, 1);
1130 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "PDU", (void *)&rsp_pdu
->bhs
, ISCSI_BHS_LEN
);
1132 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
1138 iscsi_check_values(struct spdk_iscsi_conn
*conn
)
1140 if (conn
->sess
->FirstBurstLength
> conn
->sess
->MaxBurstLength
) {
1141 SPDK_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n",
1142 conn
->sess
->FirstBurstLength
,
1143 conn
->sess
->MaxBurstLength
);
1146 if (conn
->sess
->FirstBurstLength
> g_spdk_iscsi
.FirstBurstLength
) {
1147 SPDK_ERRLOG("FirstBurstLength(%d) > iSCSI target restriction(%d)\n",
1148 conn
->sess
->FirstBurstLength
, g_spdk_iscsi
.FirstBurstLength
);
1151 if (conn
->sess
->MaxBurstLength
> 0x00ffffff) {
1152 SPDK_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n",
1153 conn
->sess
->MaxBurstLength
);
1157 if (conn
->MaxRecvDataSegmentLength
< 512) {
1158 SPDK_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n",
1159 conn
->MaxRecvDataSegmentLength
);
1162 if (conn
->MaxRecvDataSegmentLength
> 0x00ffffff) {
1163 SPDK_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n",
1164 conn
->MaxRecvDataSegmentLength
);
1171 * The response function of spdk_iscsi_op_login
1177 iscsi_op_login_response(struct spdk_iscsi_conn
*conn
,
1178 struct spdk_iscsi_pdu
*rsp_pdu
, struct iscsi_param
*params
)
1180 struct iscsi_bhs_login_rsp
*rsph
;
1183 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1184 rsph
->version_max
= ISCSI_VERSION
;
1185 rsph
->version_act
= ISCSI_VERSION
;
1186 DSET24(rsph
->data_segment_len
, rsp_pdu
->data_segment_len
);
1188 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
1191 if (conn
->sess
!= NULL
) {
1192 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
1193 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
1195 to_be32(&rsph
->exp_cmd_sn
, rsp_pdu
->cmd_sn
);
1196 to_be32(&rsph
->max_cmd_sn
, rsp_pdu
->cmd_sn
);
1199 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "PDU", (uint8_t *)rsph
, ISCSI_BHS_LEN
);
1200 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "DATA", rsp_pdu
->data
, rsp_pdu
->data_segment_len
);
1202 /* Set T/CSG/NSG to reserved if login error. */
1203 if (rsph
->status_class
!= 0) {
1204 rsph
->flags
&= ~ISCSI_LOGIN_TRANSIT
;
1205 rsph
->flags
&= ~ISCSI_LOGIN_CURRENT_STAGE_MASK
;
1206 rsph
->flags
&= ~ISCSI_LOGIN_NEXT_STAGE_MASK
;
1208 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
1210 /* after send PDU digest on/off */
1211 if (conn
->full_feature
) {
1212 /* update internal variables */
1213 rc
= spdk_iscsi_copy_param2var(conn
);
1215 SPDK_ERRLOG("spdk_iscsi_copy_param2var() failed\n");
1216 spdk_iscsi_param_free(params
);
1220 rc
= iscsi_check_values(conn
);
1222 SPDK_ERRLOG("iscsi_check_values() failed\n");
1223 spdk_iscsi_param_free(params
);
1228 spdk_iscsi_param_free(params
);
1233 * This function is used to del the original param and update it with new
1240 iscsi_op_login_update_param(struct spdk_iscsi_conn
*conn
,
1241 const char *key
, const char *value
,
1245 struct iscsi_param
*new_param
, *orig_param
;
1248 orig_param
= spdk_iscsi_param_find(conn
->params
, key
);
1249 if (orig_param
== NULL
) {
1250 SPDK_ERRLOG("orig_param %s not found\n", key
);
1251 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1254 index
= orig_param
->state_index
;
1255 rc
= spdk_iscsi_param_del(&conn
->params
, key
);
1257 SPDK_ERRLOG("iscsi_param_del(%s) failed\n", key
);
1258 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1260 rc
= spdk_iscsi_param_add(&conn
->params
, key
, value
, list
, ISPT_LIST
);
1262 SPDK_ERRLOG("iscsi_param_add() failed\n");
1263 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1265 new_param
= spdk_iscsi_param_find(conn
->params
, key
);
1266 if (new_param
== NULL
) {
1267 SPDK_ERRLOG("spdk_iscsi_param_find() failed\n");
1268 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1270 new_param
->state_index
= index
;
1275 iscsi_negotiate_chap_param(struct spdk_iscsi_conn
*conn
, bool disable_chap
,
1276 bool require_chap
, bool mutual_chap
)
1281 conn
->require_chap
= false;
1282 rc
= iscsi_op_login_update_param(conn
, "AuthMethod", "None", "None");
1286 } else if (require_chap
) {
1287 conn
->require_chap
= true;
1288 rc
= iscsi_op_login_update_param(conn
, "AuthMethod", "CHAP", "CHAP");
1294 conn
->mutual_chap
= true;
1301 * The function which is used to handle the part of session discovery
1307 iscsi_op_login_session_discovery_chap(struct spdk_iscsi_conn
*conn
)
1309 return iscsi_negotiate_chap_param(conn
, g_spdk_iscsi
.disable_chap
,
1310 g_spdk_iscsi
.require_chap
,
1311 g_spdk_iscsi
.mutual_chap
);
1315 * This function is used to update the param related with chap
1321 iscsi_op_login_negotiate_chap_param(struct spdk_iscsi_conn
*conn
,
1322 struct spdk_iscsi_tgt_node
*target
)
1324 return iscsi_negotiate_chap_param(conn
, target
->disable_chap
,
1325 target
->require_chap
,
1326 target
->mutual_chap
);
1330 iscsi_op_login_negotiate_digest_param(struct spdk_iscsi_conn
*conn
,
1331 struct spdk_iscsi_tgt_node
*target
)
1335 if (target
->header_digest
) {
1337 * User specified header digests, so update the list of
1338 * HeaderDigest values to remove "None" so that only
1339 * initiators who support CRC32C can connect.
1341 rc
= iscsi_op_login_update_param(conn
, "HeaderDigest", "CRC32C", "CRC32C");
1347 if (target
->data_digest
) {
1349 * User specified data digests, so update the list of
1350 * DataDigest values to remove "None" so that only
1351 * initiators who support CRC32C can connect.
1353 rc
= iscsi_op_login_update_param(conn
, "DataDigest", "CRC32C", "CRC32C");
1363 * This function use to check the session
1369 iscsi_op_login_check_session(struct spdk_iscsi_conn
*conn
,
1370 struct spdk_iscsi_pdu
*rsp_pdu
,
1371 char *initiator_port_name
, int cid
)
1375 struct iscsi_bhs_login_rsp
*rsph
;
1377 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1378 /* check existing session */
1379 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "isid=%"PRIx64
", tsih=%u, cid=%u\n",
1380 iscsi_get_isid(rsph
->isid
), from_be16(&rsph
->tsih
), cid
);
1381 if (rsph
->tsih
!= 0) {
1382 /* multiple connections */
1383 rc
= append_iscsi_sess(conn
, initiator_port_name
,
1384 from_be16(&rsph
->tsih
), cid
);
1386 SPDK_ERRLOG("isid=%"PRIx64
", tsih=%u, cid=%u:"
1387 "spdk_append_iscsi_sess() failed\n",
1388 iscsi_get_isid(rsph
->isid
), from_be16(&rsph
->tsih
),
1390 /* Can't include in session */
1391 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1392 rsph
->status_detail
= rc
;
1393 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1395 } else if (!g_spdk_iscsi
.AllowDuplicateIsid
) {
1396 /* new session, drop old sess by the initiator */
1397 spdk_iscsi_drop_conns(conn
, initiator_port_name
, 0 /* drop old */);
1404 * This function is used to check the target info
1410 iscsi_op_login_check_target(struct spdk_iscsi_conn
*conn
,
1411 struct spdk_iscsi_pdu
*rsp_pdu
,
1412 const char *target_name
,
1413 struct spdk_iscsi_tgt_node
**target
)
1416 struct iscsi_bhs_login_rsp
*rsph
;
1418 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1419 *target
= spdk_iscsi_find_tgt_node(target_name
);
1420 if (*target
== NULL
) {
1421 SPDK_WARNLOG("target %s not found\n", target_name
);
1423 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1424 rsph
->status_detail
= ISCSI_LOGIN_TARGET_NOT_FOUND
;
1425 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1427 if (spdk_iscsi_tgt_node_is_destructed(*target
)) {
1428 SPDK_ERRLOG("target %s is removed\n", target_name
);
1429 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1430 rsph
->status_detail
= ISCSI_LOGIN_TARGET_REMOVED
;
1431 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1433 result
= spdk_iscsi_tgt_node_access(conn
, *target
,
1434 conn
->initiator_name
,
1435 conn
->initiator_addr
);
1437 SPDK_ERRLOG("access denied\n");
1438 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1439 rsph
->status_detail
= ISCSI_LOGIN_AUTHORIZATION_FAIL
;
1440 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1447 * The function which is used to handle the part of normal login session
1450 * SPDK_ISCSI_LOGIN_ERROR_PARAMETER, parameter error;
1453 iscsi_op_login_session_normal(struct spdk_iscsi_conn
*conn
,
1454 struct spdk_iscsi_pdu
*rsp_pdu
,
1455 char *initiator_port_name
,
1456 struct iscsi_param
*params
,
1457 struct spdk_iscsi_tgt_node
**target
,
1460 const char *target_name
;
1461 const char *target_short_name
;
1462 struct iscsi_bhs_login_rsp
*rsph
;
1465 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1466 target_name
= spdk_iscsi_param_get_val(params
, "TargetName");
1468 if (target_name
== NULL
) {
1469 SPDK_ERRLOG("TargetName is empty\n");
1470 /* Missing parameter */
1471 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1472 rsph
->status_detail
= ISCSI_LOGIN_MISSING_PARMS
;
1473 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1476 memset(conn
->target_short_name
, 0, MAX_TARGET_NAME
);
1477 target_short_name
= strstr(target_name
, ":");
1478 if (target_short_name
!= NULL
) {
1479 target_short_name
++; /* Advance past the ':' */
1480 if (strlen(target_short_name
) >= MAX_TARGET_NAME
) {
1481 SPDK_ERRLOG("Target Short Name (%s) is more than %u characters\n",
1482 target_short_name
, MAX_TARGET_NAME
);
1485 snprintf(conn
->target_short_name
, MAX_TARGET_NAME
, "%s",
1489 pthread_mutex_lock(&g_spdk_iscsi
.mutex
);
1490 rc
= iscsi_op_login_check_target(conn
, rsp_pdu
, target_name
, target
);
1491 pthread_mutex_unlock(&g_spdk_iscsi
.mutex
);
1497 conn
->target
= *target
;
1498 conn
->dev
= (*target
)->dev
;
1499 conn
->target_port
= spdk_scsi_dev_find_port_by_id((*target
)->dev
,
1500 conn
->portal
->group
->tag
);
1502 rc
= iscsi_op_login_check_session(conn
, rsp_pdu
,
1503 initiator_port_name
, cid
);
1508 /* force target flags */
1509 pthread_mutex_lock(&((*target
)->mutex
));
1510 rc
= iscsi_op_login_negotiate_chap_param(conn
, *target
);
1511 pthread_mutex_unlock(&((*target
)->mutex
));
1517 return iscsi_op_login_negotiate_digest_param(conn
, *target
);
1521 * This function is used to judge the session type
1527 iscsi_op_login_session_type(struct spdk_iscsi_conn
*conn
,
1528 struct spdk_iscsi_pdu
*rsp_pdu
,
1529 enum session_type
*session_type
,
1530 struct iscsi_param
*params
)
1532 const char *session_type_str
;
1533 struct iscsi_bhs_login_rsp
*rsph
;
1535 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1536 session_type_str
= spdk_iscsi_param_get_val(params
, "SessionType");
1537 if (session_type_str
== NULL
) {
1538 if (rsph
->tsih
!= 0) {
1539 *session_type
= SESSION_TYPE_NORMAL
;
1541 SPDK_ERRLOG("SessionType is empty\n");
1542 /* Missing parameter */
1543 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1544 rsph
->status_detail
= ISCSI_LOGIN_MISSING_PARMS
;
1545 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1548 if (strcasecmp(session_type_str
, "Discovery") == 0) {
1549 *session_type
= SESSION_TYPE_DISCOVERY
;
1550 } else if (strcasecmp(session_type_str
, "Normal") == 0) {
1551 *session_type
= SESSION_TYPE_NORMAL
;
1553 *session_type
= SESSION_TYPE_INVALID
;
1554 SPDK_ERRLOG("SessionType is invalid\n");
1555 /* Missing parameter */
1556 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1557 rsph
->status_detail
= ISCSI_LOGIN_MISSING_PARMS
;
1558 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1561 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Session Type: %s\n", session_type_str
);
1566 * This function is used to initialize the port info
1572 iscsi_op_login_initialize_port(struct spdk_iscsi_conn
*conn
,
1573 struct spdk_iscsi_pdu
*rsp_pdu
,
1574 char *initiator_port_name
,
1575 uint32_t name_length
,
1576 struct iscsi_param
*params
)
1579 struct iscsi_bhs_login_rsp
*rsph
;
1580 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1582 /* Initiator Name and Port */
1583 val
= spdk_iscsi_param_get_val(params
, "InitiatorName");
1585 SPDK_ERRLOG("InitiatorName is empty\n");
1586 /* Missing parameter */
1587 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1588 rsph
->status_detail
= ISCSI_LOGIN_MISSING_PARMS
;
1589 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1591 snprintf(conn
->initiator_name
, sizeof(conn
->initiator_name
), "%s", val
);
1592 snprintf(initiator_port_name
, name_length
,
1593 "%s,i,0x%12.12" PRIx64
, val
, iscsi_get_isid(rsph
->isid
));
1594 spdk_strlwr(conn
->initiator_name
);
1595 spdk_strlwr(initiator_port_name
);
1596 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Initiator name: %s\n", conn
->initiator_name
);
1597 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Initiator port: %s\n", initiator_port_name
);
1603 * This function is used to set the info in the connection data structure
1609 iscsi_op_login_set_conn_info(struct spdk_iscsi_conn
*conn
,
1610 struct spdk_iscsi_pdu
*rsp_pdu
,
1611 char *initiator_port_name
,
1612 enum session_type session_type
,
1613 struct spdk_iscsi_tgt_node
*target
, int cid
)
1616 struct iscsi_bhs_login_rsp
*rsph
;
1617 struct spdk_scsi_port
*initiator_port
;
1619 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1620 conn
->authenticated
= false;
1621 conn
->auth
.chap_phase
= ISCSI_CHAP_PHASE_WAIT_A
;
1624 if (conn
->sess
== NULL
) {
1625 /* create initiator port */
1626 initiator_port
= spdk_scsi_port_create(iscsi_get_isid(rsph
->isid
), 0, initiator_port_name
);
1627 if (initiator_port
== NULL
) {
1628 SPDK_ERRLOG("create_port() failed\n");
1629 rsph
->status_class
= ISCSI_CLASS_TARGET_ERROR
;
1630 rsph
->status_detail
= ISCSI_LOGIN_STATUS_NO_RESOURCES
;
1631 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1635 rc
= create_iscsi_sess(conn
, target
, session_type
);
1637 spdk_scsi_port_free(&initiator_port
);
1638 SPDK_ERRLOG("create_sess() failed\n");
1639 rsph
->status_class
= ISCSI_CLASS_TARGET_ERROR
;
1640 rsph
->status_detail
= ISCSI_LOGIN_STATUS_NO_RESOURCES
;
1641 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1643 /* initialize parameters */
1644 conn
->sess
->initiator_port
= initiator_port
;
1645 conn
->StatSN
= from_be32(&rsph
->stat_sn
);
1646 conn
->sess
->isid
= iscsi_get_isid(rsph
->isid
);
1648 /* Initiator port TransportID */
1649 spdk_scsi_port_set_iscsi_transport_id(conn
->sess
->initiator_port
,
1650 conn
->initiator_name
,
1653 /* Discovery sessions will not have a target. */
1654 if (target
!= NULL
) {
1655 conn
->sess
->queue_depth
= target
->queue_depth
;
1658 * Assume discovery sessions have an effective command
1659 * windows size of 1.
1661 conn
->sess
->queue_depth
= 1;
1663 conn
->sess
->ExpCmdSN
= rsp_pdu
->cmd_sn
;
1664 conn
->sess
->MaxCmdSN
= rsp_pdu
->cmd_sn
+ conn
->sess
->queue_depth
- 1;
1667 conn
->initiator_port
= conn
->sess
->initiator_port
;
1673 * This function is used to set the target info
1679 iscsi_op_login_set_target_info(struct spdk_iscsi_conn
*conn
,
1680 struct spdk_iscsi_pdu
*rsp_pdu
,
1681 enum session_type session_type
,
1683 struct spdk_iscsi_tgt_node
*target
)
1685 char buf
[MAX_TMPBUF
];
1688 struct spdk_iscsi_portal
*portal
= conn
->portal
;
1690 /* declarative parameters */
1691 if (target
!= NULL
) {
1692 pthread_mutex_lock(&target
->mutex
);
1693 if (target
->alias
!= NULL
) {
1694 snprintf(buf
, sizeof buf
, "%s", target
->alias
);
1696 snprintf(buf
, sizeof buf
, "%s", "");
1698 pthread_mutex_unlock(&target
->mutex
);
1699 rc
= spdk_iscsi_param_set(conn
->sess
->params
, "TargetAlias", buf
);
1701 SPDK_ERRLOG("iscsi_param_set() failed\n");
1702 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1705 snprintf(buf
, sizeof buf
, "%s:%s,%d", portal
->host
, portal
->port
,
1706 portal
->group
->tag
);
1707 rc
= spdk_iscsi_param_set(conn
->sess
->params
, "TargetAddress", buf
);
1709 SPDK_ERRLOG("iscsi_param_set() failed\n");
1710 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1712 snprintf(buf
, sizeof buf
, "%d", portal
->group
->tag
);
1713 rc
= spdk_iscsi_param_set(conn
->sess
->params
, "TargetPortalGroupTag", buf
);
1715 SPDK_ERRLOG("iscsi_param_set() failed\n");
1716 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1719 /* write in response */
1720 if (target
!= NULL
) {
1721 val
= spdk_iscsi_param_get_val(conn
->sess
->params
, "TargetAlias");
1722 if (val
!= NULL
&& strlen(val
) != 0) {
1723 rsp_pdu
->data_segment_len
= iscsi_append_param(conn
,
1727 rsp_pdu
->data_segment_len
);
1729 if (session_type
== SESSION_TYPE_DISCOVERY
) {
1730 rsp_pdu
->data_segment_len
= iscsi_append_param(conn
,
1734 rsp_pdu
->data_segment_len
);
1736 rsp_pdu
->data_segment_len
= iscsi_append_param(conn
,
1737 "TargetPortalGroupTag",
1740 rsp_pdu
->data_segment_len
);
1747 * This function is used to handle the login of iscsi initiator when there is
1751 * SPDK_ISCSI_LOGIN_ERROR_PARAMETER, parameter error;
1752 * SPDK_ISCSI_LOGIN_ERROR_RESPONSE, used to notify the login fail.
1755 iscsi_op_login_phase_none(struct spdk_iscsi_conn
*conn
,
1756 struct spdk_iscsi_pdu
*rsp_pdu
,
1757 struct iscsi_param
*params
,
1758 int alloc_len
, int cid
)
1760 enum session_type session_type
;
1761 char initiator_port_name
[MAX_INITIATOR_PORT_NAME
];
1762 struct iscsi_bhs_login_rsp
*rsph
;
1763 struct spdk_iscsi_tgt_node
*target
= NULL
;
1765 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1767 conn
->target
= NULL
;
1770 rc
= iscsi_op_login_initialize_port(conn
, rsp_pdu
, initiator_port_name
,
1771 MAX_INITIATOR_PORT_NAME
, params
);
1776 rc
= iscsi_op_login_session_type(conn
, rsp_pdu
, &session_type
, params
);
1781 /* Target Name and Port */
1782 if (session_type
== SESSION_TYPE_NORMAL
) {
1783 rc
= iscsi_op_login_session_normal(conn
, rsp_pdu
,
1784 initiator_port_name
,
1785 params
, &target
, cid
);
1790 } else if (session_type
== SESSION_TYPE_DISCOVERY
) {
1794 /* force target flags */
1795 pthread_mutex_lock(&g_spdk_iscsi
.mutex
);
1796 rc
= iscsi_op_login_session_discovery_chap(conn
);
1797 pthread_mutex_unlock(&g_spdk_iscsi
.mutex
);
1802 SPDK_ERRLOG("unknown session type\n");
1803 /* Missing parameter */
1804 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1805 rsph
->status_detail
= ISCSI_LOGIN_MISSING_PARMS
;
1806 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1809 rc
= iscsi_op_login_set_conn_info(conn
, rsp_pdu
, initiator_port_name
,
1810 session_type
, target
, cid
);
1815 /* limit conns on discovery session */
1816 if (session_type
== SESSION_TYPE_DISCOVERY
) {
1817 conn
->sess
->MaxConnections
= 1;
1818 rc
= spdk_iscsi_param_set_int(conn
->sess
->params
,
1820 conn
->sess
->MaxConnections
);
1822 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
1823 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1827 return iscsi_op_login_set_target_info(conn
, rsp_pdu
, session_type
,
1832 * The function which is used to initialize the internal response data
1833 * structure of iscsi login function.
1839 iscsi_op_login_rsp_init(struct spdk_iscsi_conn
*conn
,
1840 struct spdk_iscsi_pdu
*pdu
, struct spdk_iscsi_pdu
*rsp_pdu
,
1841 struct iscsi_param
**params
, int *alloc_len
, int *cid
)
1843 struct iscsi_bhs_login_req
*reqh
;
1844 struct iscsi_bhs_login_rsp
*rsph
;
1847 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1848 rsph
->opcode
= ISCSI_OP_LOGIN_RSP
;
1849 rsph
->status_class
= ISCSI_CLASS_SUCCESS
;
1850 rsph
->status_detail
= ISCSI_LOGIN_ACCEPT
;
1851 rsp_pdu
->data_segment_len
= 0;
1853 /* Default MaxRecvDataSegmentLength - RFC3720(12.12) */
1854 if (conn
->MaxRecvDataSegmentLength
< 8192) {
1857 *alloc_len
= conn
->MaxRecvDataSegmentLength
;
1860 rsp_pdu
->data
= calloc(1, *alloc_len
);
1861 if (!rsp_pdu
->data
) {
1862 SPDK_ERRLOG("calloc() failed for data segment\n");
1866 reqh
= (struct iscsi_bhs_login_req
*)&pdu
->bhs
;
1867 rsph
->flags
|= (reqh
->flags
& ISCSI_LOGIN_TRANSIT
);
1868 rsph
->flags
|= (reqh
->flags
& ISCSI_LOGIN_CONTINUE
);
1869 rsph
->flags
|= (reqh
->flags
& ISCSI_LOGIN_CURRENT_STAGE_MASK
);
1870 if (ISCSI_BHS_LOGIN_GET_TBIT(rsph
->flags
)) {
1871 rsph
->flags
|= (reqh
->flags
& ISCSI_LOGIN_NEXT_STAGE_MASK
);
1874 /* We don't need to convert from network byte order. Just store it */
1875 memcpy(&rsph
->isid
, reqh
->isid
, 6);
1876 rsph
->tsih
= reqh
->tsih
;
1877 rsph
->itt
= reqh
->itt
;
1878 rsp_pdu
->cmd_sn
= from_be32(&reqh
->cmd_sn
);
1879 *cid
= from_be16(&reqh
->cid
);
1882 rsph
->stat_sn
= reqh
->exp_stat_sn
;
1885 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "PDU", (uint8_t *)&pdu
->bhs
, ISCSI_BHS_LEN
);
1887 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
1888 "T=%d, C=%d, CSG=%d, NSG=%d, Min=%d, Max=%d, ITT=%x\n",
1889 ISCSI_BHS_LOGIN_GET_TBIT(rsph
->flags
),
1890 ISCSI_BHS_LOGIN_GET_CBIT(rsph
->flags
),
1891 ISCSI_BHS_LOGIN_GET_CSG(rsph
->flags
),
1892 ISCSI_BHS_LOGIN_GET_NSG(rsph
->flags
),
1893 reqh
->version_min
, reqh
->version_max
, from_be32(&rsph
->itt
));
1895 if (conn
->sess
!= NULL
) {
1896 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
1897 "CmdSN=%u, ExpStatSN=%u, StatSN=%u, ExpCmdSN=%u,"
1898 "MaxCmdSN=%u\n", rsp_pdu
->cmd_sn
,
1899 from_be32(&rsph
->stat_sn
), conn
->StatSN
,
1900 conn
->sess
->ExpCmdSN
,
1901 conn
->sess
->MaxCmdSN
);
1903 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
1904 "CmdSN=%u, ExpStatSN=%u, StatSN=%u\n",
1905 rsp_pdu
->cmd_sn
, from_be32(&rsph
->stat_sn
),
1909 if (ISCSI_BHS_LOGIN_GET_TBIT(rsph
->flags
) &&
1910 ISCSI_BHS_LOGIN_GET_CBIT(rsph
->flags
)) {
1911 SPDK_ERRLOG("transit error\n");
1912 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1914 /* make sure reqh->version_max < ISCSI_VERSION */
1915 if (reqh
->version_min
> ISCSI_VERSION
) {
1916 SPDK_ERRLOG("unsupported version min %d/max %d, expecting %d\n", reqh
->version_min
,
1917 reqh
->version_max
, ISCSI_VERSION
);
1918 /* Unsupported version */
1919 /* set all reserved flag to zero */
1920 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1921 rsph
->status_detail
= ISCSI_LOGIN_UNSUPPORTED_VERSION
;
1922 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1925 if ((ISCSI_BHS_LOGIN_GET_NSG(rsph
->flags
) == ISCSI_NSG_RESERVED_CODE
) &&
1926 ISCSI_BHS_LOGIN_GET_TBIT(rsph
->flags
)) {
1927 /* set NSG to zero */
1928 rsph
->flags
&= ~ISCSI_LOGIN_NEXT_STAGE_MASK
;
1929 /* also set other bits to zero */
1930 rsph
->flags
&= ~ISCSI_LOGIN_TRANSIT
;
1931 rsph
->flags
&= ~ISCSI_LOGIN_CURRENT_STAGE_MASK
;
1932 SPDK_ERRLOG("Received reserved NSG code: %d\n", ISCSI_NSG_RESERVED_CODE
);
1933 /* Initiator error */
1934 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1935 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
1936 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1939 /* store incoming parameters */
1940 rc
= spdk_iscsi_parse_params(params
, pdu
->data
,
1941 pdu
->data_segment_len
, ISCSI_BHS_LOGIN_GET_CBIT(reqh
->flags
),
1942 &conn
->partial_text_parameter
);
1944 SPDK_ERRLOG("iscsi_parse_params() failed\n");
1945 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1946 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
1947 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER
;
1953 * This function is used to set the csg bit case in rsp
1959 iscsi_op_login_rsp_handle_csg_bit(struct spdk_iscsi_conn
*conn
,
1960 struct spdk_iscsi_pdu
*rsp_pdu
,
1961 struct iscsi_param
*params
, int alloc_len
)
1963 const char *auth_method
;
1965 struct iscsi_bhs_login_rsp
*rsph
;
1966 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
1968 switch (ISCSI_BHS_LOGIN_GET_CSG(rsph
->flags
)) {
1969 case ISCSI_SECURITY_NEGOTIATION_PHASE
:
1970 /* SecurityNegotiation */
1971 auth_method
= spdk_iscsi_param_get_val(conn
->params
, "AuthMethod");
1972 if (auth_method
== NULL
) {
1973 SPDK_ERRLOG("AuthMethod is empty\n");
1974 /* Missing parameter */
1975 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1976 rsph
->status_detail
= ISCSI_LOGIN_MISSING_PARMS
;
1977 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1979 if (strcasecmp(auth_method
, "None") == 0) {
1980 conn
->authenticated
= true;
1982 rc
= iscsi_auth_params(conn
, params
, auth_method
,
1983 rsp_pdu
->data
, alloc_len
,
1984 rsp_pdu
->data_segment_len
);
1986 SPDK_ERRLOG("iscsi_auth_params() failed\n");
1987 /* Authentication failure */
1988 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
1989 rsph
->status_detail
= ISCSI_LOGIN_AUTHENT_FAIL
;
1990 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
1992 rsp_pdu
->data_segment_len
= rc
;
1993 if (!conn
->authenticated
) {
1995 rsph
->flags
&= ~ISCSI_LOGIN_TRANSIT
;
1997 if (conn
->auth
.chap_phase
!= ISCSI_CHAP_PHASE_END
) {
1998 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "CHAP phase not complete");
2002 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "Negotiated Auth Params",
2003 rsp_pdu
->data
, rsp_pdu
->data_segment_len
);
2007 case ISCSI_OPERATIONAL_NEGOTIATION_PHASE
:
2008 /* LoginOperationalNegotiation */
2009 if (conn
->state
== ISCSI_CONN_STATE_INVALID
) {
2010 if (conn
->require_chap
) {
2011 /* Authentication failure */
2012 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2013 rsph
->status_detail
= ISCSI_LOGIN_AUTHENT_FAIL
;
2014 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2016 /* AuthMethod=None */
2017 conn
->authenticated
= true;
2020 if (!conn
->authenticated
) {
2021 SPDK_ERRLOG("authentication error\n");
2022 /* Authentication failure */
2023 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2024 rsph
->status_detail
= ISCSI_LOGIN_AUTHENT_FAIL
;
2025 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2029 case ISCSI_FULL_FEATURE_PHASE
:
2030 /* FullFeaturePhase */
2031 SPDK_ERRLOG("XXX Login in FullFeaturePhase\n");
2032 /* Initiator error */
2033 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2034 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
2035 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2038 SPDK_ERRLOG("unknown stage\n");
2039 /* Initiator error */
2040 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2041 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
2042 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2048 /* This function is used to notify the session info
2054 iscsi_op_login_notify_session_info(struct spdk_iscsi_conn
*conn
,
2055 struct spdk_iscsi_pdu
*rsp_pdu
)
2057 struct iscsi_bhs_login_rsp
*rsph
;
2059 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
2060 if (conn
->sess
->session_type
== SESSION_TYPE_NORMAL
) {
2061 /* normal session */
2062 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Login from %s (%s) on %s tgt_node%d"
2063 " (%s:%s,%d), ISID=%"PRIx64
", TSIH=%u,"
2064 " CID=%u, HeaderDigest=%s, DataDigest=%s\n",
2065 conn
->initiator_name
, conn
->initiator_addr
,
2066 conn
->target
->name
, conn
->target
->num
,
2067 conn
->portal
->host
, conn
->portal
->port
, conn
->portal
->group
->tag
,
2068 conn
->sess
->isid
, conn
->sess
->tsih
, conn
->cid
,
2069 (spdk_iscsi_param_eq_val(conn
->params
, "HeaderDigest", "CRC32C")
2071 (spdk_iscsi_param_eq_val(conn
->params
, "DataDigest", "CRC32C")
2073 } else if (conn
->sess
->session_type
== SESSION_TYPE_DISCOVERY
) {
2074 /* discovery session */
2075 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Login(discovery) from %s (%s) on"
2076 " (%s:%s,%d), ISID=%"PRIx64
", TSIH=%u,"
2077 " CID=%u, HeaderDigest=%s, DataDigest=%s\n",
2078 conn
->initiator_name
, conn
->initiator_addr
,
2079 conn
->portal
->host
, conn
->portal
->port
, conn
->portal
->group
->tag
,
2080 conn
->sess
->isid
, conn
->sess
->tsih
, conn
->cid
,
2081 (spdk_iscsi_param_eq_val(conn
->params
, "HeaderDigest", "CRC32C")
2083 (spdk_iscsi_param_eq_val(conn
->params
, "DataDigest", "CRC32C")
2086 SPDK_ERRLOG("unknown session type\n");
2087 /* Initiator error */
2088 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2089 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
2090 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2097 * This function is to handle the tbit cases
2103 iscsi_op_login_rsp_handle_t_bit(struct spdk_iscsi_conn
*conn
,
2104 struct spdk_iscsi_pdu
*rsp_pdu
)
2107 struct iscsi_bhs_login_rsp
*rsph
;
2108 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
2110 switch (ISCSI_BHS_LOGIN_GET_NSG(rsph
->flags
)) {
2111 case ISCSI_SECURITY_NEGOTIATION_PHASE
:
2112 /* SecurityNegotiation */
2113 conn
->login_phase
= ISCSI_SECURITY_NEGOTIATION_PHASE
;
2116 case ISCSI_OPERATIONAL_NEGOTIATION_PHASE
:
2117 /* LoginOperationalNegotiation */
2118 conn
->login_phase
= ISCSI_OPERATIONAL_NEGOTIATION_PHASE
;
2121 case ISCSI_FULL_FEATURE_PHASE
:
2122 /* FullFeaturePhase */
2123 conn
->login_phase
= ISCSI_FULL_FEATURE_PHASE
;
2124 to_be16(&rsph
->tsih
, conn
->sess
->tsih
);
2126 rc
= iscsi_op_login_notify_session_info(conn
, rsp_pdu
);
2131 conn
->full_feature
= 1;
2135 SPDK_ERRLOG("unknown stage\n");
2136 /* Initiator error */
2137 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2138 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
2139 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2146 * This function is used to set the values of the internal data structure used
2147 * by spdk_iscsi_op_login function
2149 * 0, used to notify the a successful login
2150 * SPDK_ISCSI_LOGIN_ERROR_RESPONSE, used to notify a failure login.
2153 iscsi_op_login_rsp_handle(struct spdk_iscsi_conn
*conn
,
2154 struct spdk_iscsi_pdu
*rsp_pdu
, struct iscsi_param
**params
,
2158 struct iscsi_bhs_login_rsp
*rsph
;
2159 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
2161 /* negotiate parameters */
2162 rc
= spdk_iscsi_negotiate_params(conn
, params
, rsp_pdu
->data
, alloc_len
,
2163 rsp_pdu
->data_segment_len
);
2166 * spdk_iscsi_negotiate_params just returns -1 on failure,
2167 * so translate this into meaningful response codes and
2170 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
2171 rsph
->status_detail
= ISCSI_LOGIN_INITIATOR_ERROR
;
2172 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
2175 rsp_pdu
->data_segment_len
= rc
;
2176 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "Negotiated Params", rsp_pdu
->data
, rc
);
2178 /* handle the CSG bit case */
2179 rc
= iscsi_op_login_rsp_handle_csg_bit(conn
, rsp_pdu
, *params
,
2185 /* handle the T bit case */
2186 if (ISCSI_BHS_LOGIN_GET_TBIT(rsph
->flags
)) {
2187 rc
= iscsi_op_login_rsp_handle_t_bit(conn
, rsp_pdu
);
2194 iscsi_op_login(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
2197 struct spdk_iscsi_pdu
*rsp_pdu
;
2198 struct iscsi_param
*params
= NULL
;
2199 struct iscsi_param
**params_p
= ¶ms
;
2203 if (conn
->full_feature
&& conn
->sess
!= NULL
&&
2204 conn
->sess
->session_type
== SESSION_TYPE_DISCOVERY
) {
2205 return SPDK_ISCSI_CONNECTION_FATAL
;
2208 rsp_pdu
= spdk_get_pdu();
2209 if (rsp_pdu
== NULL
) {
2210 return SPDK_ISCSI_CONNECTION_FATAL
;
2212 rc
= iscsi_op_login_rsp_init(conn
, pdu
, rsp_pdu
, params_p
,
2214 if (rc
== SPDK_ISCSI_LOGIN_ERROR_RESPONSE
|| rc
== SPDK_ISCSI_LOGIN_ERROR_PARAMETER
) {
2215 iscsi_op_login_response(conn
, rsp_pdu
, *params_p
);
2219 /* For other values, we need to directly return */
2221 spdk_put_pdu(rsp_pdu
);
2225 if (conn
->state
== ISCSI_CONN_STATE_INVALID
) {
2226 rc
= iscsi_op_login_phase_none(conn
, rsp_pdu
, *params_p
,
2228 if (rc
== SPDK_ISCSI_LOGIN_ERROR_RESPONSE
|| rc
== SPDK_ISCSI_LOGIN_ERROR_PARAMETER
) {
2229 iscsi_op_login_response(conn
, rsp_pdu
, *params_p
);
2234 rc
= iscsi_op_login_rsp_handle(conn
, rsp_pdu
, params_p
, alloc_len
);
2235 if (rc
== SPDK_ISCSI_LOGIN_ERROR_RESPONSE
) {
2236 iscsi_op_login_response(conn
, rsp_pdu
, *params_p
);
2240 rc
= iscsi_op_login_response(conn
, rsp_pdu
, *params_p
);
2242 conn
->state
= ISCSI_CONN_STATE_RUNNING
;
2243 if (conn
->full_feature
!= 0) {
2244 spdk_iscsi_conn_schedule(conn
);
2247 SPDK_ERRLOG("login error - connection will be destroyed\n");
2254 iscsi_op_text(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
2256 struct iscsi_param
*params
= NULL
;
2257 struct iscsi_param
**params_p
= ¶ms
;
2258 struct spdk_iscsi_pdu
*rsp_pdu
;
2269 struct iscsi_bhs_text_req
*reqh
;
2270 struct iscsi_bhs_text_resp
*rsph
;
2273 alloc_len
= conn
->MaxRecvDataSegmentLength
;
2275 reqh
= (struct iscsi_bhs_text_req
*)&pdu
->bhs
;
2277 F_bit
= !!(reqh
->flags
& ISCSI_FLAG_FINAL
);
2278 C_bit
= !!(reqh
->flags
& ISCSI_TEXT_CONTINUE
);
2279 lun
= from_be64(&reqh
->lun
);
2280 task_tag
= from_be32(&reqh
->itt
);
2281 CmdSN
= from_be32(&reqh
->cmd_sn
);
2282 pdu
->cmd_sn
= CmdSN
;
2283 ExpStatSN
= from_be32(&reqh
->exp_stat_sn
);
2285 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "I=%d, F=%d, C=%d, ITT=%x, TTT=%x\n",
2286 reqh
->immediate
, F_bit
, C_bit
, task_tag
, from_be32(&reqh
->ttt
));
2288 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
2289 "CmdSN=%u, ExpStatSN=%u, StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
2290 CmdSN
, ExpStatSN
, conn
->StatSN
, conn
->sess
->ExpCmdSN
,
2291 conn
->sess
->MaxCmdSN
);
2293 if (ExpStatSN
!= conn
->StatSN
) {
2295 SPDK_ERRLOG("StatSN(%u) error\n", ExpStatSN
);
2298 /* StarPort have a bug */
2299 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN(%u) rewound\n", ExpStatSN
);
2300 conn
->StatSN
= ExpStatSN
;
2304 if (F_bit
&& C_bit
) {
2305 SPDK_ERRLOG("final and continue\n");
2310 * If this is the first text op in a sequence, save the ITT so we can
2311 * compare it against the ITT for subsequent ops in the same sequence.
2312 * If a subsequent text op in same sequence has a different ITT, reject
2315 if (conn
->sess
->current_text_itt
== 0xffffffffU
) {
2316 conn
->sess
->current_text_itt
= task_tag
;
2317 } else if (conn
->sess
->current_text_itt
!= task_tag
) {
2318 SPDK_ERRLOG("The correct itt is %u, and the current itt is %u...\n",
2319 conn
->sess
->current_text_itt
, task_tag
);
2320 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
2323 /* store incoming parameters */
2324 rc
= spdk_iscsi_parse_params(¶ms
, pdu
->data
, pdu
->data_segment_len
,
2325 C_bit
, &conn
->partial_text_parameter
);
2327 SPDK_ERRLOG("iscsi_parse_params() failed\n");
2328 spdk_iscsi_param_free(params
);
2332 data
= calloc(1, alloc_len
);
2334 SPDK_ERRLOG("calloc() failed for data segment\n");
2335 spdk_iscsi_param_free(params
);
2339 /* negotiate parameters */
2340 data_len
= spdk_iscsi_negotiate_params(conn
, params_p
,
2341 data
, alloc_len
, data_len
);
2343 SPDK_ERRLOG("spdk_iscsi_negotiate_params() failed\n");
2344 spdk_iscsi_param_free(*params_p
);
2349 /* sendtargets is special case */
2350 val
= spdk_iscsi_param_get_val(*params_p
, "SendTargets");
2352 if (spdk_iscsi_param_eq_val(conn
->sess
->params
,
2353 "SessionType", "Discovery")) {
2354 if (strcasecmp(val
, "") == 0) {
2358 data_len
= spdk_iscsi_send_tgts(conn
,
2359 conn
->initiator_name
,
2360 conn
->initiator_addr
,
2361 val
, data
, alloc_len
,
2364 if (strcasecmp(val
, "") == 0) {
2365 val
= conn
->target
->name
;
2368 if (strcasecmp(val
, "ALL") == 0) {
2369 /* not in discovery session */
2370 data_len
= iscsi_append_text(conn
,
2373 alloc_len
, data_len
);
2375 data_len
= spdk_iscsi_send_tgts(conn
,
2376 conn
->initiator_name
,
2377 conn
->initiator_addr
,
2378 val
, data
, alloc_len
,
2383 if (spdk_iscsi_param_eq_val(conn
->sess
->params
, "SessionType", "Discovery")) {
2384 spdk_iscsi_param_free(*params_p
);
2386 return SPDK_ISCSI_CONNECTION_FATAL
;
2390 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "Negotiated Params", data
, data_len
);
2393 rsp_pdu
= spdk_get_pdu();
2394 if (rsp_pdu
== NULL
) {
2395 spdk_iscsi_param_free(*params_p
);
2397 return SPDK_ISCSI_CONNECTION_FATAL
;
2399 rsph
= (struct iscsi_bhs_text_resp
*)&rsp_pdu
->bhs
;
2401 rsp_pdu
->data
= data
;
2402 rsph
->opcode
= ISCSI_OP_TEXT_RSP
;
2405 rsph
->flags
|= ISCSI_FLAG_FINAL
;
2409 rsph
->flags
|= ISCSI_TEXT_CONTINUE
;
2412 DSET24(rsph
->data_segment_len
, data_len
);
2413 to_be64(&rsph
->lun
, lun
);
2414 to_be32(&rsph
->itt
, task_tag
);
2417 rsph
->ttt
= 0xffffffffU
;
2418 conn
->sess
->current_text_itt
= 0xffffffffU
;
2420 to_be32(&rsph
->ttt
, 1 + conn
->id
);
2423 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
2426 if (reqh
->immediate
== 0) {
2427 conn
->sess
->MaxCmdSN
++;
2430 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
2431 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
2433 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
2435 /* update internal variables */
2436 rc
= spdk_iscsi_copy_param2var(conn
);
2438 SPDK_ERRLOG("spdk_iscsi_copy_param2var() failed\n");
2439 spdk_iscsi_param_free(*params_p
);
2444 rc
= iscsi_check_values(conn
);
2446 SPDK_ERRLOG("iscsi_check_values() failed\n");
2447 spdk_iscsi_param_free(*params_p
);
2451 spdk_iscsi_param_free(*params_p
);
2456 iscsi_op_logout(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
2458 struct spdk_iscsi_pdu
*rsp_pdu
;
2463 struct iscsi_bhs_logout_req
*reqh
;
2464 struct iscsi_bhs_logout_resp
*rsph
;
2467 reqh
= (struct iscsi_bhs_logout_req
*)&pdu
->bhs
;
2469 cid
= from_be16(&reqh
->cid
);
2470 task_tag
= from_be32(&reqh
->itt
);
2471 CmdSN
= from_be32(&reqh
->cmd_sn
);
2472 pdu
->cmd_sn
= CmdSN
;
2473 ExpStatSN
= from_be32(&reqh
->exp_stat_sn
);
2475 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "reason=%d, ITT=%x, cid=%d\n",
2476 reqh
->reason
, task_tag
, cid
);
2478 if (reqh
->reason
!= 0 && conn
->sess
->session_type
== SESSION_TYPE_DISCOVERY
) {
2479 SPDK_ERRLOG("only logout with close the session reason can be in discovery session");
2480 return SPDK_ISCSI_CONNECTION_FATAL
;
2483 if (conn
->sess
!= NULL
) {
2484 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
2485 "CmdSN=%u, ExpStatSN=%u, StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
2486 CmdSN
, ExpStatSN
, conn
->StatSN
,
2487 conn
->sess
->ExpCmdSN
, conn
->sess
->MaxCmdSN
);
2489 if (CmdSN
!= conn
->sess
->ExpCmdSN
) {
2490 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "CmdSN(%u) might have dropped\n", CmdSN
);
2494 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "CmdSN=%u, ExpStatSN=%u, StatSN=%u\n",
2495 CmdSN
, ExpStatSN
, conn
->StatSN
);
2498 if (ExpStatSN
!= conn
->StatSN
) {
2499 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN(%u/%u) might have dropped\n",
2500 ExpStatSN
, conn
->StatSN
);
2504 if (conn
->id
== cid
) {
2505 /* connection or session closed successfully */
2507 spdk_iscsi_conn_logout(conn
);
2513 rsp_pdu
= spdk_get_pdu();
2514 if (rsp_pdu
== NULL
) {
2515 return SPDK_ISCSI_CONNECTION_FATAL
;
2517 rsph
= (struct iscsi_bhs_logout_resp
*)&rsp_pdu
->bhs
;
2518 rsp_pdu
->data
= NULL
;
2519 rsph
->opcode
= ISCSI_OP_LOGOUT_RSP
;
2520 rsph
->flags
|= 0x80; /* bit 0 must be 1 */
2521 rsph
->response
= response
;
2522 DSET24(rsph
->data_segment_len
, 0);
2523 to_be32(&rsph
->itt
, task_tag
);
2525 if (conn
->sess
!= NULL
) {
2526 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
2529 if (conn
->sess
->connections
== 1) {
2530 conn
->sess
->MaxCmdSN
++;
2533 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
2534 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
2536 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
2538 to_be32(&rsph
->exp_cmd_sn
, CmdSN
);
2539 to_be32(&rsph
->max_cmd_sn
, CmdSN
);
2542 rsph
->time_2_wait
= 0;
2543 rsph
->time_2_retain
= 0;
2545 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
2547 if (conn
->sess
== NULL
) {
2549 * login failed but initiator still sent a logout rather than
2550 * just closing the TCP connection.
2552 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Logout(login failed) from %s (%s) on"
2554 conn
->initiator_name
, conn
->initiator_addr
,
2555 conn
->portal_host
, conn
->portal_port
, conn
->pg_tag
);
2556 } else if (spdk_iscsi_param_eq_val(conn
->sess
->params
, "SessionType", "Normal")) {
2557 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Logout from %s (%s) on %s tgt_node%d"
2558 " (%s:%s,%d), ISID=%"PRIx64
", TSIH=%u,"
2559 " CID=%u, HeaderDigest=%s, DataDigest=%s\n",
2560 conn
->initiator_name
, conn
->initiator_addr
,
2561 conn
->target
->name
, conn
->target
->num
,
2562 conn
->portal_host
, conn
->portal_port
, conn
->pg_tag
,
2563 conn
->sess
->isid
, conn
->sess
->tsih
, conn
->cid
,
2564 (spdk_iscsi_param_eq_val(conn
->params
, "HeaderDigest", "CRC32C")
2566 (spdk_iscsi_param_eq_val(conn
->params
, "DataDigest", "CRC32C")
2569 /* discovery session */
2570 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Logout(discovery) from %s (%s) on"
2571 " (%s:%s,%d), ISID=%"PRIx64
", TSIH=%u,"
2572 " CID=%u, HeaderDigest=%s, DataDigest=%s\n",
2573 conn
->initiator_name
, conn
->initiator_addr
,
2574 conn
->portal_host
, conn
->portal_port
, conn
->pg_tag
,
2575 conn
->sess
->isid
, conn
->sess
->tsih
, conn
->cid
,
2576 (spdk_iscsi_param_eq_val(conn
->params
, "HeaderDigest", "CRC32C")
2578 (spdk_iscsi_param_eq_val(conn
->params
, "DataDigest", "CRC32C")
2585 /* This function returns the spdk_scsi_task by searching the snack list via
2586 * task transfertag and the pdu's opcode
2588 static struct spdk_iscsi_task
*
2589 get_scsi_task_from_ttt(struct spdk_iscsi_conn
*conn
, uint32_t transfer_tag
)
2591 struct spdk_iscsi_pdu
*pdu
;
2592 struct iscsi_bhs_data_in
*datain_bhs
;
2594 TAILQ_FOREACH(pdu
, &conn
->snack_pdu_list
, tailq
) {
2595 if (pdu
->bhs
.opcode
== ISCSI_OP_SCSI_DATAIN
) {
2596 datain_bhs
= (struct iscsi_bhs_data_in
*)&pdu
->bhs
;
2597 if (from_be32(&datain_bhs
->ttt
) == transfer_tag
) {
2606 /* This function returns the spdk_scsi_task by searching the snack list via
2607 * initiator task tag and the pdu's opcode
2609 static struct spdk_iscsi_task
*
2610 get_scsi_task_from_itt(struct spdk_iscsi_conn
*conn
,
2611 uint32_t task_tag
, enum iscsi_op opcode
)
2613 struct spdk_iscsi_pdu
*pdu
;
2615 TAILQ_FOREACH(pdu
, &conn
->snack_pdu_list
, tailq
) {
2616 if (pdu
->bhs
.opcode
== opcode
&&
2617 pdu
->task
!= NULL
&&
2618 pdu
->task
->tag
== task_tag
) {
2627 iscsi_send_datain(struct spdk_iscsi_conn
*conn
,
2628 struct spdk_iscsi_task
*task
, int datain_flag
,
2629 int residual_len
, int offset
, int DataSN
, int len
)
2631 struct spdk_iscsi_pdu
*rsp_pdu
;
2632 struct iscsi_bhs_data_in
*rsph
;
2634 uint32_t transfer_tag
;
2635 int F_bit
, U_bit
, O_bit
, S_bit
;
2636 struct spdk_iscsi_task
*primary
;
2638 primary
= spdk_iscsi_task_get_primary(task
);
2641 rsp_pdu
= spdk_get_pdu();
2642 rsph
= (struct iscsi_bhs_data_in
*)&rsp_pdu
->bhs
;
2643 rsp_pdu
->data
= task
->scsi
.iovs
[0].iov_base
+ offset
;
2644 rsp_pdu
->data_buf_len
= task
->scsi
.iovs
[0].iov_len
- offset
;
2645 rsp_pdu
->data_from_mempool
= true;
2647 task_tag
= task
->tag
;
2648 transfer_tag
= 0xffffffffU
;
2650 F_bit
= datain_flag
& ISCSI_FLAG_FINAL
;
2651 O_bit
= datain_flag
& ISCSI_DATAIN_OVERFLOW
;
2652 U_bit
= datain_flag
& ISCSI_DATAIN_UNDERFLOW
;
2653 S_bit
= datain_flag
& ISCSI_DATAIN_STATUS
;
2656 * we need to hold onto this task/cmd because until the
2657 * PDU has been written out
2659 rsp_pdu
->task
= task
;
2662 rsph
->opcode
= ISCSI_OP_SCSI_DATAIN
;
2665 rsph
->flags
|= ISCSI_FLAG_FINAL
;
2668 /* we leave the A_bit clear */
2670 if (F_bit
&& S_bit
) {
2672 rsph
->flags
|= ISCSI_DATAIN_OVERFLOW
;
2676 rsph
->flags
|= ISCSI_DATAIN_UNDERFLOW
;
2681 rsph
->flags
|= ISCSI_DATAIN_STATUS
;
2682 rsph
->status
= task
->scsi
.status
;
2685 DSET24(rsph
->data_segment_len
, len
);
2687 to_be32(&rsph
->itt
, task_tag
);
2688 to_be32(&rsph
->ttt
, transfer_tag
);
2691 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
2695 if (F_bit
&& S_bit
&& !spdk_iscsi_task_is_immediate(primary
)) {
2696 conn
->sess
->MaxCmdSN
++;
2699 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
2700 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
2702 to_be32(&rsph
->data_sn
, DataSN
);
2704 if (conn
->sess
->ErrorRecoveryLevel
>= 1) {
2705 primary
->datain_datasn
= DataSN
;
2710 offset
+= primary
->scsi
.data_transferred
;
2712 to_be32(&rsph
->buffer_offset
, (uint32_t)offset
);
2714 if (F_bit
&& S_bit
) {
2715 to_be32(&rsph
->res_cnt
, residual_len
);
2718 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
2724 iscsi_transfer_in(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_task
*task
)
2731 int residual_len
= 0;
2734 int datain_flag
= 0;
2738 struct spdk_iscsi_task
*primary
;
2740 primary
= spdk_iscsi_task_get_primary(task
);
2741 segment_len
= conn
->MaxRecvDataSegmentLength
;
2742 data_len
= task
->scsi
.data_transferred
;
2743 transfer_len
= task
->scsi
.length
;
2745 if (task
->scsi
.status
!= SPDK_SCSI_STATUS_GOOD
) {
2746 if (task
!= primary
) {
2747 conn
->data_in_cnt
--;
2748 /* Handle the case when primary task return success but the subtask failed */
2749 if (primary
->bytes_completed
== primary
->scsi
.transfer_len
&&
2750 primary
->scsi
.status
== SPDK_SCSI_STATUS_GOOD
) {
2751 conn
->data_in_cnt
--;
2754 /* handle the case that it is a primary task which has subtasks */
2755 if (primary
->scsi
.transfer_len
!= primary
->scsi
.length
) {
2756 conn
->data_in_cnt
--;
2763 if (data_len
< transfer_len
) {
2765 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Underflow %u/%u\n", data_len
, transfer_len
);
2766 residual_len
= transfer_len
- data_len
;
2767 transfer_len
= data_len
;
2768 datain_flag
|= ISCSI_DATAIN_UNDERFLOW
;
2769 } else if (data_len
> transfer_len
) {
2771 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Overflow %u/%u\n", data_len
, transfer_len
);
2772 residual_len
= data_len
- transfer_len
;
2773 datain_flag
|= ISCSI_DATAIN_OVERFLOW
;
2775 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Transfer %u\n", transfer_len
);
2779 DataSN
= primary
->datain_datasn
;
2782 /* calculate the number of sequences for all data-in pdus */
2783 datain_seq_cnt
= 1 + ((transfer_len
- 1) / (int)conn
->sess
->MaxBurstLength
);
2784 for (i
= 0; i
< datain_seq_cnt
; i
++) {
2785 offset
= i
* conn
->sess
->MaxBurstLength
;
2786 sequence_end
= DMIN32(((i
+ 1) * conn
->sess
->MaxBurstLength
),
2789 /* send data splitted by segment_len */
2790 for (; offset
< sequence_end
; offset
+= segment_len
) {
2791 len
= DMIN32(segment_len
, (sequence_end
- offset
));
2793 datain_flag
&= ~ISCSI_FLAG_FINAL
;
2794 datain_flag
&= ~ISCSI_DATAIN_STATUS
;
2796 if (offset
+ len
== sequence_end
) {
2797 /* last PDU in a sequence */
2798 datain_flag
|= ISCSI_FLAG_FINAL
;
2799 if (task
->scsi
.sense_data_len
== 0) {
2800 /* The last pdu in all data-in pdus */
2801 if ((offset
+ len
) == transfer_len
&&
2802 (primary
->bytes_completed
== primary
->scsi
.transfer_len
)) {
2803 datain_flag
|= ISCSI_DATAIN_STATUS
;
2809 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Transfer=%d, Offset=%d, Len=%d\n",
2810 sequence_end
, offset
, len
);
2811 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN=%u, DataSN=%u, Offset=%u, Len=%d\n",
2812 conn
->StatSN
, DataSN
, offset
, len
);
2814 DataSN
= iscsi_send_datain(conn
, task
, datain_flag
, residual_len
,
2815 offset
, DataSN
, len
);
2819 if (task
!= primary
) {
2820 primary
->scsi
.data_transferred
+= task
->scsi
.data_transferred
;
2822 primary
->datain_datasn
= DataSN
;
2828 * This function compare the input pdu's bhs with the pdu's bhs associated by
2829 * active_r2t_tasks and queued_r2t_tasks in a connection
2832 iscsi_compare_pdu_bhs_within_existed_r2t_tasks(struct spdk_iscsi_conn
*conn
,
2833 struct spdk_iscsi_pdu
*pdu
)
2835 struct spdk_iscsi_task
*task
;
2837 TAILQ_FOREACH(task
, &conn
->active_r2t_tasks
, link
) {
2838 if (!memcmp(&pdu
->bhs
, spdk_iscsi_task_get_bhs(task
), ISCSI_BHS_LEN
)) {
2843 TAILQ_FOREACH(task
, &conn
->queued_r2t_tasks
, link
) {
2844 if (!memcmp(&pdu
->bhs
, spdk_iscsi_task_get_bhs(task
), ISCSI_BHS_LEN
)) {
2853 iscsi_queue_task(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_task
*task
)
2855 spdk_trace_record(TRACE_ISCSI_TASK_QUEUE
, conn
->id
, task
->scsi
.length
,
2856 (uintptr_t)task
, (uintptr_t)task
->pdu
);
2857 task
->is_queued
= true;
2858 spdk_scsi_dev_queue_task(conn
->dev
, &task
->scsi
);
2862 iscsi_queue_mgmt_task(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_task
*task
)
2864 spdk_scsi_dev_queue_mgmt_task(conn
->dev
, &task
->scsi
);
2867 int spdk_iscsi_conn_handle_queued_datain_tasks(struct spdk_iscsi_conn
*conn
)
2869 struct spdk_iscsi_task
*task
;
2871 while (!TAILQ_EMPTY(&conn
->queued_datain_tasks
) &&
2872 conn
->data_in_cnt
< MAX_LARGE_DATAIN_PER_CONNECTION
) {
2873 task
= TAILQ_FIRST(&conn
->queued_datain_tasks
);
2874 assert(task
->current_datain_offset
<= task
->scsi
.transfer_len
);
2876 if (task
->current_datain_offset
== 0) {
2877 task
->scsi
.lun
= spdk_scsi_dev_get_lun(conn
->dev
, task
->lun_id
);
2878 if (task
->scsi
.lun
== NULL
) {
2879 TAILQ_REMOVE(&conn
->queued_datain_tasks
, task
, link
);
2880 spdk_scsi_task_process_null_lun(&task
->scsi
);
2881 spdk_iscsi_task_cpl(&task
->scsi
);
2884 task
->current_datain_offset
= task
->scsi
.length
;
2885 conn
->data_in_cnt
++;
2886 iscsi_queue_task(conn
, task
);
2889 if (task
->current_datain_offset
< task
->scsi
.transfer_len
) {
2890 struct spdk_iscsi_task
*subtask
;
2891 uint32_t remaining_size
= 0;
2893 remaining_size
= task
->scsi
.transfer_len
- task
->current_datain_offset
;
2894 subtask
= spdk_iscsi_task_get(conn
, task
, spdk_iscsi_task_cpl
);
2895 assert(subtask
!= NULL
);
2896 subtask
->scsi
.offset
= task
->current_datain_offset
;
2897 subtask
->scsi
.length
= DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE
, remaining_size
);
2898 spdk_scsi_task_set_data(&subtask
->scsi
, NULL
, 0);
2899 task
->current_datain_offset
+= subtask
->scsi
.length
;
2900 conn
->data_in_cnt
++;
2902 task
->scsi
.lun
= spdk_scsi_dev_get_lun(conn
->dev
, task
->lun_id
);
2903 if (task
->scsi
.lun
== NULL
) {
2904 /* Remove the primary task from the list if this is the last subtask */
2905 if (task
->current_datain_offset
== task
->scsi
.transfer_len
) {
2906 TAILQ_REMOVE(&conn
->queued_datain_tasks
, task
, link
);
2908 subtask
->scsi
.transfer_len
= subtask
->scsi
.length
;
2909 spdk_scsi_task_process_null_lun(&subtask
->scsi
);
2910 spdk_iscsi_task_cpl(&subtask
->scsi
);
2914 iscsi_queue_task(conn
, subtask
);
2916 if (task
->current_datain_offset
== task
->scsi
.transfer_len
) {
2917 TAILQ_REMOVE(&conn
->queued_datain_tasks
, task
, link
);
2924 iscsi_op_scsi_read(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_task
*task
)
2926 int32_t remaining_size
;
2928 TAILQ_INIT(&task
->subtask_list
);
2929 task
->scsi
.dxfer_dir
= SPDK_SCSI_DIR_FROM_DEV
;
2930 task
->parent
= NULL
;
2931 task
->scsi
.offset
= 0;
2932 task
->scsi
.length
= DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE
, task
->scsi
.transfer_len
);
2933 spdk_scsi_task_set_data(&task
->scsi
, NULL
, 0);
2935 remaining_size
= task
->scsi
.transfer_len
- task
->scsi
.length
;
2936 task
->current_datain_offset
= 0;
2938 if (remaining_size
== 0) {
2939 iscsi_queue_task(conn
, task
);
2943 TAILQ_INSERT_TAIL(&conn
->queued_datain_tasks
, task
, link
);
2945 return spdk_iscsi_conn_handle_queued_datain_tasks(conn
);
2949 iscsi_op_scsi(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
2951 struct spdk_iscsi_task
*task
;
2952 struct spdk_scsi_dev
*dev
;
2956 uint32_t transfer_len
;
2957 uint32_t scsi_data_len
;
2958 int F_bit
, R_bit
, W_bit
;
2960 struct iscsi_bhs_scsi_req
*reqh
;
2962 if (conn
->sess
->session_type
!= SESSION_TYPE_NORMAL
) {
2963 SPDK_ERRLOG("ISCSI_OP_SCSI not allowed in discovery and invalid session\n");
2964 return SPDK_ISCSI_CONNECTION_FATAL
;
2967 reqh
= (struct iscsi_bhs_scsi_req
*)&pdu
->bhs
;
2969 F_bit
= reqh
->final_bit
;
2970 R_bit
= reqh
->read_bit
;
2971 W_bit
= reqh
->write_bit
;
2972 lun
= from_be64(&reqh
->lun
);
2973 task_tag
= from_be32(&reqh
->itt
);
2974 transfer_len
= from_be32(&reqh
->expected_data_xfer_len
);
2977 SPDK_LOGDUMP(SPDK_LOG_ISCSI
, "CDB", cdb
, 16);
2979 task
= spdk_iscsi_task_get(conn
, NULL
, spdk_iscsi_task_cpl
);
2981 SPDK_ERRLOG("Unable to acquire task\n");
2982 return SPDK_ISCSI_CONNECTION_FATAL
;
2985 spdk_iscsi_task_associate_pdu(task
, pdu
);
2986 lun_i
= spdk_scsi_lun_id_fmt_to_int(lun
);
2987 task
->lun_id
= lun_i
;
2989 task
->scsi
.lun
= spdk_scsi_dev_get_lun(dev
, lun_i
);
2991 if ((R_bit
!= 0) && (W_bit
!= 0)) {
2992 SPDK_ERRLOG("Bidirectional CDB is not supported\n");
2993 spdk_iscsi_task_put(task
);
2994 return SPDK_ISCSI_CONNECTION_FATAL
;
2997 task
->scsi
.cdb
= cdb
;
2998 task
->tag
= task_tag
;
2999 task
->scsi
.transfer_len
= transfer_len
;
3000 task
->scsi
.target_port
= conn
->target_port
;
3001 task
->scsi
.initiator_port
= conn
->initiator_port
;
3002 task
->parent
= NULL
;
3003 task
->rsp_scsi_status
= SPDK_SCSI_STATUS_GOOD
;
3005 if (task
->scsi
.lun
== NULL
) {
3006 spdk_scsi_task_process_null_lun(&task
->scsi
);
3007 spdk_iscsi_task_cpl(&task
->scsi
);
3011 /* no bi-directional support */
3013 return iscsi_op_scsi_read(conn
, task
);
3015 task
->scsi
.dxfer_dir
= SPDK_SCSI_DIR_TO_DEV
;
3017 if ((conn
->sess
->ErrorRecoveryLevel
>= 1) &&
3018 (iscsi_compare_pdu_bhs_within_existed_r2t_tasks(conn
, pdu
))) {
3019 spdk_iscsi_task_response(conn
, task
);
3020 spdk_iscsi_task_put(task
);
3024 if (pdu
->data_segment_len
> transfer_len
) {
3025 SPDK_ERRLOG("data segment len(=%d) > task transfer len(=%d)\n",
3026 (int)pdu
->data_segment_len
, transfer_len
);
3027 spdk_iscsi_task_put(task
);
3028 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
3031 /* check the ImmediateData and also pdu->data_segment_len */
3032 if ((!conn
->sess
->ImmediateData
&& (pdu
->data_segment_len
> 0)) ||
3033 (pdu
->data_segment_len
> conn
->sess
->FirstBurstLength
)) {
3034 spdk_iscsi_task_put(task
);
3035 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
3038 if (spdk_likely(!pdu
->dif_insert_or_strip
)) {
3039 scsi_data_len
= pdu
->data_segment_len
;
3041 scsi_data_len
= pdu
->data_buf_len
;
3044 if (F_bit
&& pdu
->data_segment_len
< transfer_len
) {
3046 rc
= add_transfer_task(conn
, task
);
3048 SPDK_ERRLOG("add_transfer_task() failed\n");
3049 spdk_iscsi_task_put(task
);
3050 return SPDK_ISCSI_CONNECTION_FATAL
;
3053 /* Non-immediate writes */
3054 if (pdu
->data_segment_len
== 0) {
3057 /* we are doing the first partial write task */
3059 spdk_scsi_task_set_data(&task
->scsi
, pdu
->data
, scsi_data_len
);
3060 task
->scsi
.length
= pdu
->data_segment_len
;
3064 if (pdu
->data_segment_len
== transfer_len
) {
3065 /* we are doing small writes with no R2T */
3066 spdk_scsi_task_set_data(&task
->scsi
, pdu
->data
, scsi_data_len
);
3067 task
->scsi
.length
= transfer_len
;
3070 /* neither R nor W bit set */
3071 task
->scsi
.dxfer_dir
= SPDK_SCSI_DIR_NONE
;
3072 if (transfer_len
> 0) {
3073 spdk_iscsi_task_put(task
);
3074 SPDK_ERRLOG("Reject scsi cmd with EDTL > 0 but (R | W) == 0\n");
3075 return iscsi_reject(conn
, pdu
, ISCSI_REASON_INVALID_PDU_FIELD
);
3079 iscsi_queue_task(conn
, task
);
3084 abort_transfer_task_in_task_mgmt_resp(struct spdk_iscsi_conn
*conn
,
3085 struct spdk_iscsi_task
*task
)
3087 struct spdk_iscsi_pdu
*pdu
;
3089 pdu
= spdk_iscsi_task_get_pdu(task
);
3091 switch (task
->scsi
.function
) {
3092 /* abort task identified by Reference Task Tag field */
3093 case ISCSI_TASK_FUNC_ABORT_TASK
:
3094 spdk_del_transfer_task(conn
, task
->scsi
.abort_id
);
3097 /* abort all tasks issued via this session on the LUN */
3098 case ISCSI_TASK_FUNC_ABORT_TASK_SET
:
3099 spdk_clear_all_transfer_task(conn
, task
->scsi
.lun
, pdu
);
3102 case ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET
:
3103 spdk_clear_all_transfer_task(conn
, task
->scsi
.lun
, pdu
);
3109 spdk_iscsi_task_mgmt_response(struct spdk_iscsi_conn
*conn
,
3110 struct spdk_iscsi_task
*task
)
3112 struct spdk_iscsi_pdu
*rsp_pdu
;
3113 struct iscsi_bhs_task_req
*reqh
;
3114 struct iscsi_bhs_task_resp
*rsph
;
3116 if (task
->pdu
== NULL
) {
3118 * This was an internally generated task management command,
3119 * usually from LUN cleanup when a connection closes.
3124 reqh
= (struct iscsi_bhs_task_req
*)&task
->pdu
->bhs
;
3126 rsp_pdu
= spdk_get_pdu();
3127 rsph
= (struct iscsi_bhs_task_resp
*)&rsp_pdu
->bhs
;
3128 rsph
->opcode
= ISCSI_OP_TASK_RSP
;
3129 rsph
->flags
|= 0x80; /* bit 0 default to 1 */
3130 switch (task
->scsi
.response
) {
3131 case SPDK_SCSI_TASK_MGMT_RESP_COMPLETE
:
3132 abort_transfer_task_in_task_mgmt_resp(conn
, task
);
3133 rsph
->response
= ISCSI_TASK_FUNC_RESP_COMPLETE
;
3135 case SPDK_SCSI_TASK_MGMT_RESP_SUCCESS
:
3136 abort_transfer_task_in_task_mgmt_resp(conn
, task
);
3137 rsph
->response
= ISCSI_TASK_FUNC_RESP_COMPLETE
;
3139 case SPDK_SCSI_TASK_MGMT_RESP_REJECT
:
3140 rsph
->response
= ISCSI_TASK_FUNC_REJECTED
;
3142 case SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN
:
3143 rsph
->response
= ISCSI_TASK_FUNC_RESP_LUN_NOT_EXIST
;
3145 case SPDK_SCSI_TASK_MGMT_RESP_TARGET_FAILURE
:
3146 rsph
->response
= ISCSI_TASK_FUNC_REJECTED
;
3148 case SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
:
3149 rsph
->response
= ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED
;
3152 rsph
->itt
= reqh
->itt
;
3154 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
3157 if (reqh
->immediate
== 0) {
3158 conn
->sess
->MaxCmdSN
++;
3161 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
3162 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
3164 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
3167 void spdk_iscsi_task_response(struct spdk_iscsi_conn
*conn
,
3168 struct spdk_iscsi_task
*task
)
3170 struct spdk_iscsi_pdu
*rsp_pdu
;
3171 struct iscsi_bhs_scsi_resp
*rsph
;
3173 uint32_t transfer_len
;
3174 size_t residual_len
;
3178 struct spdk_iscsi_task
*primary
;
3180 primary
= spdk_iscsi_task_get_primary(task
);
3182 transfer_len
= primary
->scsi
.transfer_len
;
3183 task_tag
= task
->tag
;
3185 /* transfer data from logical unit */
3186 /* (direction is view of initiator side) */
3187 if (spdk_iscsi_task_is_read(primary
)) {
3188 rc
= iscsi_transfer_in(conn
, task
);
3190 /* sent status by last DATAIN PDU */
3194 if (primary
->bytes_completed
!= primary
->scsi
.transfer_len
) {
3201 data_len
= primary
->scsi
.data_transferred
;
3203 if ((transfer_len
!= 0) &&
3204 (task
->scsi
.status
== SPDK_SCSI_STATUS_GOOD
)) {
3205 if (data_len
< transfer_len
) {
3207 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Underflow %zu/%u\n", data_len
, transfer_len
);
3208 residual_len
= transfer_len
- data_len
;
3210 } else if (data_len
> transfer_len
) {
3212 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Overflow %zu/%u\n", data_len
, transfer_len
);
3213 residual_len
= data_len
- transfer_len
;
3216 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Transfer %u\n", transfer_len
);
3221 rsp_pdu
= spdk_get_pdu();
3222 assert(rsp_pdu
!= NULL
);
3223 rsph
= (struct iscsi_bhs_scsi_resp
*)&rsp_pdu
->bhs
;
3224 assert(task
->scsi
.sense_data_len
<= sizeof(rsp_pdu
->sense
.data
));
3225 memcpy(rsp_pdu
->sense
.data
, task
->scsi
.sense_data
, task
->scsi
.sense_data_len
);
3226 to_be16(&rsp_pdu
->sense
.length
, task
->scsi
.sense_data_len
);
3227 rsp_pdu
->data
= (uint8_t *)&rsp_pdu
->sense
;
3228 rsp_pdu
->data_from_mempool
= true;
3231 * we need to hold onto this task/cmd because until the
3232 * PDU has been written out
3234 rsp_pdu
->task
= task
;
3237 rsph
->opcode
= ISCSI_OP_SCSI_RSP
;
3238 rsph
->flags
|= 0x80; /* bit 0 is default to 1 */
3241 rsph
->flags
|= ISCSI_SCSI_OVERFLOW
;
3245 rsph
->flags
|= ISCSI_SCSI_UNDERFLOW
;
3248 rsph
->status
= task
->scsi
.status
;
3249 if (task
->scsi
.sense_data_len
) {
3250 /* SenseLength (2 bytes) + SenseData */
3251 DSET24(rsph
->data_segment_len
, 2 + task
->scsi
.sense_data_len
);
3253 to_be32(&rsph
->itt
, task_tag
);
3255 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
3258 if (!spdk_iscsi_task_is_immediate(primary
)) {
3259 conn
->sess
->MaxCmdSN
++;
3262 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
3263 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
3265 to_be32(&rsph
->bi_read_res_cnt
, 0);
3266 to_be32(&rsph
->res_cnt
, residual_len
);
3268 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
3271 static struct spdk_iscsi_task
*
3272 get_transfer_task(struct spdk_iscsi_conn
*conn
, uint32_t transfer_tag
)
3276 for (i
= 0; i
< conn
->pending_r2t
; i
++) {
3277 if (conn
->outstanding_r2t_tasks
[i
]->ttt
== transfer_tag
) {
3278 return (conn
->outstanding_r2t_tasks
[i
]);
3286 _iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn
*conn
,
3287 struct spdk_iscsi_task
*task
)
3289 struct spdk_iscsi_task
*subtask
;
3290 uint32_t remaining_size
;
3292 while (conn
->data_in_cnt
< MAX_LARGE_DATAIN_PER_CONNECTION
) {
3293 assert(task
->current_datain_offset
<= task
->scsi
.transfer_len
);
3295 /* If no IO is submitted yet, just abort the primary task. */
3296 if (task
->current_datain_offset
== 0) {
3297 TAILQ_REMOVE(&conn
->queued_datain_tasks
, task
, link
);
3298 spdk_scsi_task_process_abort(&task
->scsi
);
3299 spdk_iscsi_task_cpl(&task
->scsi
);
3303 /* If any IO is submitted already, abort all subtasks by repetition. */
3304 if (task
->current_datain_offset
< task
->scsi
.transfer_len
) {
3305 remaining_size
= task
->scsi
.transfer_len
- task
->current_datain_offset
;
3306 subtask
= spdk_iscsi_task_get(conn
, task
, spdk_iscsi_task_cpl
);
3307 assert(subtask
!= NULL
);
3308 subtask
->scsi
.offset
= task
->current_datain_offset
;
3309 subtask
->scsi
.length
= DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE
, remaining_size
);
3310 spdk_scsi_task_set_data(&subtask
->scsi
, NULL
, 0);
3311 task
->current_datain_offset
+= subtask
->scsi
.length
;
3312 conn
->data_in_cnt
++;
3314 subtask
->scsi
.transfer_len
= subtask
->scsi
.length
;
3315 spdk_scsi_task_process_abort(&subtask
->scsi
);
3316 spdk_iscsi_task_cpl(&subtask
->scsi
);
3319 /* Remove the primary task from the list if this is the last subtask */
3320 if (task
->current_datain_offset
== task
->scsi
.transfer_len
) {
3321 TAILQ_REMOVE(&conn
->queued_datain_tasks
, task
, link
);
3330 iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn
*conn
,
3331 uint32_t ref_task_tag
)
3333 struct spdk_iscsi_task
*task
;
3335 TAILQ_FOREACH(task
, &conn
->queued_datain_tasks
, link
) {
3336 if (task
->tag
== ref_task_tag
) {
3337 return _iscsi_conn_abort_queued_datain_task(conn
, task
);
3345 iscsi_conn_abort_queued_datain_tasks(struct spdk_iscsi_conn
*conn
,
3346 struct spdk_scsi_lun
*lun
,
3347 struct spdk_iscsi_pdu
*pdu
)
3349 struct spdk_iscsi_task
*task
, *task_tmp
;
3350 struct spdk_iscsi_pdu
*pdu_tmp
;
3353 TAILQ_FOREACH_SAFE(task
, &conn
->queued_datain_tasks
, link
, task_tmp
) {
3354 pdu_tmp
= spdk_iscsi_task_get_pdu(task
);
3355 if ((lun
== NULL
|| lun
== task
->scsi
.lun
) &&
3356 (pdu
== NULL
|| (SN32_LT(pdu_tmp
->cmd_sn
, pdu
->cmd_sn
)))) {
3357 rc
= _iscsi_conn_abort_queued_datain_task(conn
, task
);
3368 _iscsi_op_abort_task(void *arg
)
3370 struct spdk_iscsi_task
*task
= arg
;
3373 rc
= iscsi_conn_abort_queued_datain_task(task
->conn
, task
->scsi
.abort_id
);
3378 spdk_poller_unregister(&task
->mgmt_poller
);
3379 iscsi_queue_mgmt_task(task
->conn
, task
);
3384 iscsi_op_abort_task(struct spdk_iscsi_task
*task
, uint32_t ref_task_tag
)
3386 task
->scsi
.abort_id
= ref_task_tag
;
3387 task
->scsi
.function
= SPDK_SCSI_TASK_FUNC_ABORT_TASK
;
3388 task
->mgmt_poller
= spdk_poller_register(_iscsi_op_abort_task
, task
, 10);
3392 _iscsi_op_abort_task_set(void *arg
)
3394 struct spdk_iscsi_task
*task
= arg
;
3397 rc
= iscsi_conn_abort_queued_datain_tasks(task
->conn
, task
->scsi
.lun
,
3403 spdk_poller_unregister(&task
->mgmt_poller
);
3404 iscsi_queue_mgmt_task(task
->conn
, task
);
3409 spdk_iscsi_op_abort_task_set(struct spdk_iscsi_task
*task
, uint8_t function
)
3411 task
->scsi
.function
= function
;
3412 task
->mgmt_poller
= spdk_poller_register(_iscsi_op_abort_task_set
, task
, 10);
3416 iscsi_op_task(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
3418 struct iscsi_bhs_task_req
*reqh
;
3421 uint32_t ref_task_tag
;
3424 struct spdk_iscsi_task
*task
;
3425 struct spdk_scsi_dev
*dev
;
3427 if (conn
->sess
->session_type
!= SESSION_TYPE_NORMAL
) {
3428 SPDK_ERRLOG("ISCSI_OP_TASK not allowed in discovery and invalid session\n");
3429 return SPDK_ISCSI_CONNECTION_FATAL
;
3432 reqh
= (struct iscsi_bhs_task_req
*)&pdu
->bhs
;
3433 function
= reqh
->flags
& ISCSI_TASK_FUNCTION_MASK
;
3434 lun
= from_be64(&reqh
->lun
);
3435 task_tag
= from_be32(&reqh
->itt
);
3436 ref_task_tag
= from_be32(&reqh
->ref_task_tag
);
3438 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "I=%d, func=%d, ITT=%x, ref TT=%x, LUN=0x%16.16"PRIx64
"\n",
3439 reqh
->immediate
, function
, task_tag
, ref_task_tag
, lun
);
3441 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
3442 conn
->StatSN
, conn
->sess
->ExpCmdSN
, conn
->sess
->MaxCmdSN
);
3444 lun_i
= spdk_scsi_lun_id_fmt_to_int(lun
);
3447 task
= spdk_iscsi_task_get(conn
, NULL
, spdk_iscsi_task_mgmt_cpl
);
3449 SPDK_ERRLOG("Unable to acquire task\n");
3450 return SPDK_ISCSI_CONNECTION_FATAL
;
3453 spdk_iscsi_task_associate_pdu(task
, pdu
);
3454 task
->scsi
.target_port
= conn
->target_port
;
3455 task
->scsi
.initiator_port
= conn
->initiator_port
;
3456 task
->tag
= task_tag
;
3457 task
->scsi
.lun
= spdk_scsi_dev_get_lun(dev
, lun_i
);
3459 if (task
->scsi
.lun
== NULL
) {
3460 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN
;
3461 spdk_iscsi_task_mgmt_response(conn
, task
);
3462 spdk_iscsi_task_put(task
);
3467 /* abort task identified by Referenced Task Tag field */
3468 case ISCSI_TASK_FUNC_ABORT_TASK
:
3469 SPDK_NOTICELOG("ABORT_TASK\n");
3471 iscsi_op_abort_task(task
, ref_task_tag
);
3474 /* abort all tasks issued via this session on the LUN */
3475 case ISCSI_TASK_FUNC_ABORT_TASK_SET
:
3476 SPDK_NOTICELOG("ABORT_TASK_SET\n");
3478 spdk_iscsi_op_abort_task_set(task
, SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET
);
3481 case ISCSI_TASK_FUNC_CLEAR_TASK_SET
:
3482 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
;
3483 SPDK_NOTICELOG("CLEAR_TASK_SET (Unsupported)\n");
3486 case ISCSI_TASK_FUNC_CLEAR_ACA
:
3487 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
;
3488 SPDK_NOTICELOG("CLEAR_ACA (Unsupported)\n");
3491 case ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET
:
3492 SPDK_NOTICELOG("LOGICAL_UNIT_RESET\n");
3494 spdk_iscsi_op_abort_task_set(task
, SPDK_SCSI_TASK_FUNC_LUN_RESET
);
3497 case ISCSI_TASK_FUNC_TARGET_WARM_RESET
:
3498 SPDK_NOTICELOG("TARGET_WARM_RESET (Unsupported)\n");
3501 spdk_iscsi_drop_conns(conn
, conn
->initiator_name
, 1 /* drop all */);
3502 rc
= spdk_iscsi_tgt_node_reset(conn
->sess
->target
, lun
);
3504 SPDK_ERRLOG("tgt_node reset failed\n");
3507 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
;
3511 case ISCSI_TASK_FUNC_TARGET_COLD_RESET
:
3512 SPDK_NOTICELOG("TARGET_COLD_RESET\n");
3515 spdk_iscsi_drop_conns(conn
, conn
->initiator_name
, 1 /* drop all */);
3517 rc
= spdk_iscsi_tgt_node_reset(conn
->sess
->target
, lun
);
3519 SPDK_ERRLOG("tgt_node reset failed\n");
3522 conn
->state
= ISCSI_CONN_STATE_EXITING
;
3524 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
;
3528 case ISCSI_TASK_FUNC_TASK_REASSIGN
:
3529 SPDK_NOTICELOG("TASK_REASSIGN (Unsupported)\n");
3530 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED
;
3534 SPDK_ERRLOG("unsupported function %d\n", function
);
3535 task
->scsi
.response
= SPDK_SCSI_TASK_MGMT_RESP_REJECT
;
3539 spdk_iscsi_task_mgmt_response(conn
, task
);
3540 spdk_iscsi_task_put(task
);
3545 iscsi_op_nopout(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
3547 struct spdk_iscsi_pdu
*rsp_pdu
;
3548 struct iscsi_bhs_nop_out
*reqh
;
3549 struct iscsi_bhs_nop_in
*rsph
;
3553 uint32_t transfer_tag
;
3558 if (conn
->sess
->session_type
== SESSION_TYPE_DISCOVERY
) {
3559 SPDK_ERRLOG("ISCSI_OP_NOPOUT not allowed in discovery session\n");
3560 return SPDK_ISCSI_CONNECTION_FATAL
;
3563 reqh
= (struct iscsi_bhs_nop_out
*)&pdu
->bhs
;
3564 I_bit
= reqh
->immediate
;
3566 data_len
= DGET24(reqh
->data_segment_len
);
3567 if (data_len
> conn
->MaxRecvDataSegmentLength
) {
3568 data_len
= conn
->MaxRecvDataSegmentLength
;
3571 lun
= from_be64(&reqh
->lun
);
3572 task_tag
= from_be32(&reqh
->itt
);
3573 transfer_tag
= from_be32(&reqh
->ttt
);
3574 CmdSN
= from_be32(&reqh
->cmd_sn
);
3575 pdu
->cmd_sn
= CmdSN
;
3577 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "I=%d, ITT=%x, TTT=%x\n",
3578 I_bit
, task_tag
, transfer_tag
);
3580 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "CmdSN=%u, StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
3581 CmdSN
, conn
->StatSN
, conn
->sess
->ExpCmdSN
,
3582 conn
->sess
->MaxCmdSN
);
3584 if (transfer_tag
!= 0xFFFFFFFF && transfer_tag
!= (uint32_t)conn
->id
) {
3585 SPDK_ERRLOG("invalid transfer tag 0x%x\n", transfer_tag
);
3587 * Technically we should probably fail the connection here, but for now
3588 * just print the error message and continue.
3593 * We don't actually check to see if this is a response to the NOP-In
3594 * that we sent. Our goal is to just verify that the initiator is
3595 * alive and responding to commands, not to verify that it tags
3596 * NOP-Outs correctly
3598 conn
->nop_outstanding
= false;
3600 if (task_tag
== 0xffffffffU
) {
3602 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "got NOPOUT ITT=0xffffffff\n");
3605 SPDK_ERRLOG("got NOPOUT ITT=0xffffffff, I=0\n");
3606 return SPDK_ISCSI_CONNECTION_FATAL
;
3610 data
= calloc(1, data_len
);
3612 SPDK_ERRLOG("calloc() failed for ping data\n");
3613 return SPDK_ISCSI_CONNECTION_FATAL
;
3616 /* response of NOPOUT */
3618 /* copy ping data */
3619 memcpy(data
, pdu
->data
, data_len
);
3622 transfer_tag
= 0xffffffffU
;
3625 rsp_pdu
= spdk_get_pdu();
3626 if (rsp_pdu
== NULL
) {
3628 return SPDK_ISCSI_CONNECTION_FATAL
;
3630 rsph
= (struct iscsi_bhs_nop_in
*)&rsp_pdu
->bhs
;
3631 rsp_pdu
->data
= data
;
3632 rsph
->opcode
= ISCSI_OP_NOPIN
;
3633 rsph
->flags
|= 0x80; /* bit 0 default to 1 */
3634 DSET24(rsph
->data_segment_len
, data_len
);
3635 to_be64(&rsph
->lun
, lun
);
3636 to_be32(&rsph
->itt
, task_tag
);
3637 to_be32(&rsph
->ttt
, transfer_tag
);
3639 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
3643 conn
->sess
->MaxCmdSN
++;
3646 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
3647 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
3649 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
3650 conn
->last_nopin
= spdk_get_ticks();
3656 add_transfer_task(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_task
*task
)
3658 uint32_t transfer_len
;
3659 size_t max_burst_len
;
3667 transfer_len
= task
->scsi
.transfer_len
;
3668 data_len
= spdk_iscsi_task_get_pdu(task
)->data_segment_len
;
3669 max_burst_len
= conn
->sess
->MaxBurstLength
;
3670 segment_len
= SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
;
3671 data_out_req
= 1 + (transfer_len
- data_len
- 1) / segment_len
;
3672 task
->data_out_cnt
= data_out_req
;
3675 * If we already have too many tasks using R2T, then queue this task
3676 * and start sending R2T for it after some of the tasks using R2T/data
3677 * out buffers complete.
3679 if (conn
->pending_r2t
>= DEFAULT_MAXR2T
) {
3680 TAILQ_INSERT_TAIL(&conn
->queued_r2t_tasks
, task
, link
);
3684 conn
->data_out_cnt
+= data_out_req
;
3685 idx
= conn
->pending_r2t
++;
3687 conn
->outstanding_r2t_tasks
[idx
] = task
;
3688 task
->next_expected_r2t_offset
= data_len
;
3689 task
->current_r2t_length
= 0;
3691 /* According to RFC3720 10.8.5, 0xffffffff is
3692 * reserved for TTT in R2T.
3694 if (++conn
->ttt
== 0xffffffffu
) {
3697 task
->ttt
= conn
->ttt
;
3699 while (data_len
!= transfer_len
) {
3700 len
= DMIN32(max_burst_len
, (transfer_len
- data_len
));
3701 rc
= iscsi_send_r2t(conn
, task
, data_len
, len
,
3702 task
->ttt
, &task
->R2TSN
);
3704 SPDK_ERRLOG("iscsi_send_r2t() failed\n");
3708 task
->next_r2t_offset
= data_len
;
3709 task
->outstanding_r2t
++;
3710 if (conn
->sess
->MaxOutstandingR2T
== task
->outstanding_r2t
) {
3715 TAILQ_INSERT_TAIL(&conn
->active_r2t_tasks
, task
, link
);
3719 /* If there are additional large writes queued for R2Ts, start them now.
3720 * This is called when a large write is just completed or when multiple LUNs
3721 * are attached and large write tasks for the specific LUN are cleared.
3724 start_queued_transfer_tasks(struct spdk_iscsi_conn
*conn
)
3726 struct spdk_iscsi_task
*task
, *tmp
;
3728 TAILQ_FOREACH_SAFE(task
, &conn
->queued_r2t_tasks
, link
, tmp
) {
3729 if (conn
->pending_r2t
< DEFAULT_MAXR2T
) {
3730 TAILQ_REMOVE(&conn
->queued_r2t_tasks
, task
, link
);
3731 add_transfer_task(conn
, task
);
3738 void spdk_del_transfer_task(struct spdk_iscsi_conn
*conn
, uint32_t task_tag
)
3740 struct spdk_iscsi_task
*task
;
3743 for (i
= 0; i
< conn
->pending_r2t
; i
++) {
3744 if (conn
->outstanding_r2t_tasks
[i
]->tag
== task_tag
) {
3745 task
= conn
->outstanding_r2t_tasks
[i
];
3746 conn
->data_out_cnt
-= task
->data_out_cnt
;
3748 conn
->pending_r2t
--;
3749 for (; i
< conn
->pending_r2t
; i
++) {
3750 conn
->outstanding_r2t_tasks
[i
] = conn
->outstanding_r2t_tasks
[i
+ 1];
3752 conn
->outstanding_r2t_tasks
[conn
->pending_r2t
] = NULL
;
3757 start_queued_transfer_tasks(conn
);
3761 del_connection_queued_task(struct spdk_iscsi_conn
*conn
, void *tailq
,
3762 struct spdk_scsi_lun
*lun
,
3763 struct spdk_iscsi_pdu
*pdu
)
3765 struct spdk_iscsi_task
*task
, *task_tmp
;
3766 struct spdk_iscsi_pdu
*pdu_tmp
;
3769 * Temporary used to index spdk_scsi_task related
3770 * queues of the connection.
3772 TAILQ_HEAD(queued_tasks
, spdk_iscsi_task
) *head
;
3773 head
= (struct queued_tasks
*)tailq
;
3775 TAILQ_FOREACH_SAFE(task
, head
, link
, task_tmp
) {
3776 pdu_tmp
= spdk_iscsi_task_get_pdu(task
);
3777 if ((lun
== NULL
|| lun
== task
->scsi
.lun
) &&
3778 (pdu
== NULL
|| SN32_LT(pdu_tmp
->cmd_sn
, pdu
->cmd_sn
))) {
3779 TAILQ_REMOVE(head
, task
, link
);
3780 if (lun
!= NULL
&& spdk_scsi_lun_is_removing(lun
)) {
3781 spdk_scsi_task_process_null_lun(&task
->scsi
);
3782 spdk_iscsi_task_response(conn
, task
);
3784 spdk_iscsi_task_put(task
);
3789 void spdk_clear_all_transfer_task(struct spdk_iscsi_conn
*conn
,
3790 struct spdk_scsi_lun
*lun
,
3791 struct spdk_iscsi_pdu
*pdu
)
3793 int i
, j
, pending_r2t
;
3794 struct spdk_iscsi_task
*task
;
3795 struct spdk_iscsi_pdu
*pdu_tmp
;
3797 pending_r2t
= conn
->pending_r2t
;
3798 for (i
= 0; i
< pending_r2t
; i
++) {
3799 task
= conn
->outstanding_r2t_tasks
[i
];
3800 pdu_tmp
= spdk_iscsi_task_get_pdu(task
);
3801 if ((lun
== NULL
|| lun
== task
->scsi
.lun
) &&
3802 (pdu
== NULL
|| SN32_LT(pdu_tmp
->cmd_sn
, pdu
->cmd_sn
))) {
3803 conn
->outstanding_r2t_tasks
[i
] = NULL
;
3804 task
->outstanding_r2t
= 0;
3805 task
->next_r2t_offset
= 0;
3806 task
->next_expected_r2t_offset
= 0;
3807 conn
->data_out_cnt
-= task
->data_out_cnt
;
3808 conn
->pending_r2t
--;
3812 for (i
= 0; i
< pending_r2t
; i
++) {
3813 if (conn
->outstanding_r2t_tasks
[i
] != NULL
) {
3816 for (j
= i
+ 1; j
< pending_r2t
; j
++) {
3817 if (conn
->outstanding_r2t_tasks
[j
] != NULL
) {
3818 conn
->outstanding_r2t_tasks
[i
] = conn
->outstanding_r2t_tasks
[j
];
3819 conn
->outstanding_r2t_tasks
[j
] = NULL
;
3825 del_connection_queued_task(conn
, &conn
->active_r2t_tasks
, lun
, pdu
);
3826 del_connection_queued_task(conn
, &conn
->queued_r2t_tasks
, lun
, pdu
);
3828 start_queued_transfer_tasks(conn
);
3831 /* This function is used to handle the r2t snack */
3833 iscsi_handle_r2t_snack(struct spdk_iscsi_conn
*conn
,
3834 struct spdk_iscsi_task
*task
,
3835 struct spdk_iscsi_pdu
*pdu
, uint32_t beg_run
,
3836 uint32_t run_length
, int32_t task_tag
)
3841 if (beg_run
< task
->acked_r2tsn
) {
3842 SPDK_ERRLOG("ITT: 0x%08x, R2T SNACK requests retransmission of"
3843 "R2TSN: from 0x%08x to 0x%08x. But it has already"
3844 "ack to R2TSN:0x%08x, protocol error.\n",
3845 task_tag
, beg_run
, (beg_run
+ run_length
),
3846 (task
->acked_r2tsn
- 1));
3847 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
3851 if ((beg_run
+ run_length
) > task
->R2TSN
) {
3852 SPDK_ERRLOG("ITT: 0x%08x, received R2T SNACK with"
3853 "BegRun: 0x%08x, RunLength: 0x%08x, exceeds"
3854 "current R2TSN: 0x%08x, protocol error.\n",
3855 task_tag
, beg_run
, run_length
,
3858 return iscsi_reject(conn
, pdu
, ISCSI_REASON_INVALID_PDU_FIELD
);
3860 last_r2tsn
= (beg_run
+ run_length
);
3862 last_r2tsn
= task
->R2TSN
;
3865 for (i
= beg_run
; i
< last_r2tsn
; i
++) {
3866 if (iscsi_send_r2t_recovery(conn
, task
, i
, false) < 0) {
3867 SPDK_ERRLOG("The r2t_sn=%d of r2t_task=%p is not sent\n", i
, task
);
3873 /* This function is used to recover the data in packet */
3875 iscsi_handle_recovery_datain(struct spdk_iscsi_conn
*conn
,
3876 struct spdk_iscsi_task
*task
,
3877 struct spdk_iscsi_pdu
*pdu
, uint32_t beg_run
,
3878 uint32_t run_length
, uint32_t task_tag
)
3880 struct spdk_iscsi_pdu
*old_pdu
, *pdu_temp
;
3882 struct iscsi_bhs_data_in
*datain_header
;
3883 uint32_t last_statsn
;
3885 task
= spdk_iscsi_task_get_primary(task
);
3887 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "iscsi_handle_recovery_datain\n");
3889 if (beg_run
< task
->acked_data_sn
) {
3890 SPDK_ERRLOG("ITT: 0x%08x, DATA IN SNACK requests retransmission of"
3891 "DATASN: from 0x%08x to 0x%08x but already acked to "
3892 "DATASN: 0x%08x protocol error\n",
3894 (beg_run
+ run_length
), (task
->acked_data_sn
- 1));
3896 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
3899 if (run_length
== 0) {
3900 /* as the DataSN begins at 0 */
3901 run_length
= task
->datain_datasn
+ 1;
3904 if ((beg_run
+ run_length
- 1) > task
->datain_datasn
) {
3905 SPDK_ERRLOG("Initiator requests BegRun: 0x%08x, RunLength:"
3906 "0x%08x greater than maximum DataSN: 0x%08x.\n",
3907 beg_run
, run_length
, task
->datain_datasn
);
3911 last_statsn
= beg_run
+ run_length
- 1;
3914 for (i
= beg_run
; i
<= last_statsn
; i
++) {
3915 TAILQ_FOREACH_SAFE(old_pdu
, &conn
->snack_pdu_list
, tailq
, pdu_temp
) {
3916 if (old_pdu
->bhs
.opcode
== ISCSI_OP_SCSI_DATAIN
) {
3917 datain_header
= (struct iscsi_bhs_data_in
*)&old_pdu
->bhs
;
3918 if (from_be32(&datain_header
->itt
) == task_tag
&&
3919 from_be32(&datain_header
->data_sn
) == i
) {
3920 TAILQ_REMOVE(&conn
->snack_pdu_list
, old_pdu
, tailq
);
3921 spdk_iscsi_conn_write_pdu(conn
, old_pdu
);
3930 /* This function is used to handle the status snack */
3932 iscsi_handle_status_snack(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
3935 uint32_t run_length
;
3936 struct iscsi_bhs_snack_req
*reqh
;
3938 uint32_t last_statsn
;
3940 struct spdk_iscsi_pdu
*old_pdu
;
3942 reqh
= (struct iscsi_bhs_snack_req
*)&pdu
->bhs
;
3943 beg_run
= from_be32(&reqh
->beg_run
);
3944 run_length
= from_be32(&reqh
->run_len
);
3946 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "beg_run=%d, run_length=%d, conn->StatSN="
3947 "%d, conn->exp_statsn=%d\n", beg_run
, run_length
,
3948 conn
->StatSN
, conn
->exp_statsn
);
3951 beg_run
= conn
->exp_statsn
;
3952 } else if (beg_run
< conn
->exp_statsn
) {
3953 SPDK_ERRLOG("Got Status SNACK Begrun: 0x%08x, RunLength: 0x%08x "
3954 "but already got ExpStatSN: 0x%08x on CID:%hu.\n",
3955 beg_run
, run_length
, conn
->StatSN
, conn
->cid
);
3957 return iscsi_reject(conn
, pdu
, ISCSI_REASON_INVALID_PDU_FIELD
);
3960 last_statsn
= (!run_length
) ? conn
->StatSN
: (beg_run
+ run_length
);
3962 for (i
= beg_run
; i
< last_statsn
; i
++) {
3964 TAILQ_FOREACH(old_pdu
, &conn
->snack_pdu_list
, tailq
) {
3965 if (from_be32(&old_pdu
->bhs
.stat_sn
) == i
) {
3972 SPDK_ERRLOG("Unable to find StatSN: 0x%08x. For a Status"
3973 "SNACK, assuming this is a proactive SNACK "
3974 "for an untransmitted StatSN, ignoring.\n",
3977 TAILQ_REMOVE(&conn
->snack_pdu_list
, old_pdu
, tailq
);
3978 spdk_iscsi_conn_write_pdu(conn
, old_pdu
);
3985 /* This function is used to handle the data ack snack */
3987 iscsi_handle_data_ack(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
3989 uint32_t transfer_tag
;
3991 uint32_t run_length
;
3992 struct spdk_iscsi_pdu
*old_pdu
;
3993 uint32_t old_datasn
;
3994 struct iscsi_bhs_snack_req
*reqh
;
3995 struct spdk_iscsi_task
*task
;
3996 struct iscsi_bhs_data_in
*datain_header
;
3997 struct spdk_iscsi_task
*primary
;
3999 reqh
= (struct iscsi_bhs_snack_req
*)&pdu
->bhs
;
4000 transfer_tag
= from_be32(&reqh
->ttt
);
4001 beg_run
= from_be32(&reqh
->beg_run
);
4002 run_length
= from_be32(&reqh
->run_len
);
4004 datain_header
= NULL
;
4006 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "beg_run=%d,transfer_tag=%d,run_len=%d\n",
4007 beg_run
, transfer_tag
, run_length
);
4009 task
= get_scsi_task_from_ttt(conn
, transfer_tag
);
4011 SPDK_ERRLOG("Data ACK SNACK for TTT: 0x%08x is invalid.\n",
4016 primary
= spdk_iscsi_task_get_primary(task
);
4017 if ((run_length
!= 0) || (beg_run
< primary
->acked_data_sn
)) {
4018 SPDK_ERRLOG("TTT: 0x%08x Data ACK SNACK BegRUN: %d is less than "
4019 "the next expected acked DataSN: %d\n",
4020 transfer_tag
, beg_run
, primary
->acked_data_sn
);
4024 primary
->acked_data_sn
= beg_run
;
4026 /* To free the pdu */
4027 TAILQ_FOREACH(old_pdu
, &conn
->snack_pdu_list
, tailq
) {
4028 if (old_pdu
->bhs
.opcode
== ISCSI_OP_SCSI_DATAIN
) {
4029 datain_header
= (struct iscsi_bhs_data_in
*) &old_pdu
->bhs
;
4030 old_datasn
= from_be32(&datain_header
->data_sn
);
4031 if ((from_be32(&datain_header
->ttt
) == transfer_tag
) &&
4032 (old_datasn
== beg_run
- 1)) {
4033 TAILQ_REMOVE(&conn
->snack_pdu_list
, old_pdu
, tailq
);
4034 if (old_pdu
->task
) {
4035 spdk_iscsi_task_put(old_pdu
->task
);
4037 spdk_put_pdu(old_pdu
);
4043 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Received Data ACK SNACK for TTT: 0x%08x,"
4044 " updated acked DataSN to 0x%08x.\n", transfer_tag
,
4045 (task
->acked_data_sn
- 1));
4050 return iscsi_reject(conn
, pdu
, ISCSI_REASON_INVALID_SNACK
);
4053 /* This function is used to remove the r2t pdu from snack_pdu_list by < task, r2t_sn> info */
4054 static struct spdk_iscsi_pdu
*
4055 iscsi_remove_r2t_pdu_from_snack_list(struct spdk_iscsi_conn
*conn
,
4056 struct spdk_iscsi_task
*task
,
4059 struct spdk_iscsi_pdu
*pdu
;
4060 struct iscsi_bhs_r2t
*r2t_header
;
4062 TAILQ_FOREACH(pdu
, &conn
->snack_pdu_list
, tailq
) {
4063 if (pdu
->bhs
.opcode
== ISCSI_OP_R2T
) {
4064 r2t_header
= (struct iscsi_bhs_r2t
*)&pdu
->bhs
;
4065 if (pdu
->task
== task
&&
4066 from_be32(&r2t_header
->r2t_sn
) == r2t_sn
) {
4067 TAILQ_REMOVE(&conn
->snack_pdu_list
, pdu
, tailq
);
4076 /* This function is used re-send the r2t packet */
4078 iscsi_send_r2t_recovery(struct spdk_iscsi_conn
*conn
,
4079 struct spdk_iscsi_task
*task
, uint32_t r2t_sn
,
4080 bool send_new_r2tsn
)
4082 struct spdk_iscsi_pdu
*pdu
;
4083 struct iscsi_bhs_r2t
*rsph
;
4084 uint32_t transfer_len
;
4088 /* remove the r2t pdu from the snack_list */
4089 pdu
= iscsi_remove_r2t_pdu_from_snack_list(conn
, task
, r2t_sn
);
4091 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "No pdu is found\n");
4096 * false: only need to re-send the old r2t with changing statsn
4097 * true: we send a r2t with new r2tsn
4099 if (!send_new_r2tsn
) {
4100 to_be32(&pdu
->bhs
.stat_sn
, conn
->StatSN
);
4101 spdk_iscsi_conn_write_pdu(conn
, pdu
);
4103 rsph
= (struct iscsi_bhs_r2t
*)&pdu
->bhs
;
4104 transfer_len
= from_be32(&rsph
->desired_xfer_len
);
4106 /* still need to increase the acked r2tsn */
4107 task
->acked_r2tsn
++;
4108 len
= DMIN32(conn
->sess
->MaxBurstLength
, (transfer_len
-
4109 task
->next_expected_r2t_offset
));
4111 /* remove the old_r2t_pdu */
4113 spdk_iscsi_task_put(pdu
->task
);
4117 /* re-send a new r2t pdu */
4118 rc
= iscsi_send_r2t(conn
, task
, task
->next_expected_r2t_offset
,
4119 len
, task
->ttt
, &task
->R2TSN
);
4121 return SPDK_ISCSI_CONNECTION_FATAL
;
4128 /* This function is used to handle the snack request from the initiator */
4130 iscsi_op_snack(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
4132 struct iscsi_bhs_snack_req
*reqh
;
4133 struct spdk_iscsi_task
*task
;
4137 uint32_t run_length
;
4140 if (conn
->sess
->session_type
== SESSION_TYPE_DISCOVERY
) {
4141 SPDK_ERRLOG("ISCSI_OP_SNACK not allowed in discovery session\n");
4142 return SPDK_ISCSI_CONNECTION_FATAL
;
4145 reqh
= (struct iscsi_bhs_snack_req
*)&pdu
->bhs
;
4146 if (!conn
->sess
->ErrorRecoveryLevel
) {
4147 SPDK_ERRLOG("Got a SNACK request in ErrorRecoveryLevel=0\n");
4148 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
4151 type
= reqh
->flags
& ISCSI_FLAG_SNACK_TYPE_MASK
;
4152 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "The value of type is %d\n", type
);
4156 reqh
= (struct iscsi_bhs_snack_req
*)&pdu
->bhs
;
4157 task_tag
= from_be32(&reqh
->itt
);
4158 beg_run
= from_be32(&reqh
->beg_run
);
4159 run_length
= from_be32(&reqh
->run_len
);
4161 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "beg_run=%d, run_length=%d, "
4162 "task_tag=%x, transfer_tag=%u\n", beg_run
,
4163 run_length
, task_tag
, from_be32(&reqh
->ttt
));
4165 task
= get_scsi_task_from_itt(conn
, task_tag
,
4166 ISCSI_OP_SCSI_DATAIN
);
4168 return iscsi_handle_recovery_datain(conn
, task
, pdu
,
4169 beg_run
, run_length
, task_tag
);
4171 task
= get_scsi_task_from_itt(conn
, task_tag
, ISCSI_OP_R2T
);
4173 return iscsi_handle_r2t_snack(conn
, task
, pdu
, beg_run
,
4174 run_length
, task_tag
);
4176 SPDK_ERRLOG("It is Neither datain nor r2t recovery request\n");
4179 case ISCSI_FLAG_SNACK_TYPE_STATUS
:
4180 rc
= iscsi_handle_status_snack(conn
, pdu
);
4182 case ISCSI_FLAG_SNACK_TYPE_DATA_ACK
:
4183 rc
= iscsi_handle_data_ack(conn
, pdu
);
4185 case ISCSI_FLAG_SNACK_TYPE_RDATA
:
4186 SPDK_ERRLOG("R-Data SNACK is Not Supported int spdk\n");
4187 rc
= iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
4190 SPDK_ERRLOG("Unknown SNACK type %d, protocol error\n", type
);
4191 rc
= iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
4198 /* This function is used to refree the pdu when it is acknowledged */
4200 remove_acked_pdu(struct spdk_iscsi_conn
*conn
, uint32_t ExpStatSN
)
4202 struct spdk_iscsi_pdu
*pdu
, *pdu_temp
;
4205 conn
->exp_statsn
= DMIN32(ExpStatSN
, conn
->StatSN
);
4206 TAILQ_FOREACH_SAFE(pdu
, &conn
->snack_pdu_list
, tailq
, pdu_temp
) {
4207 stat_sn
= from_be32(&pdu
->bhs
.stat_sn
);
4208 if (SN32_LT(stat_sn
, conn
->exp_statsn
)) {
4209 TAILQ_REMOVE(&conn
->snack_pdu_list
, pdu
, tailq
);
4210 spdk_iscsi_conn_free_pdu(conn
, pdu
);
4216 iscsi_op_data(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
4218 struct spdk_iscsi_task
*task
, *subtask
;
4219 struct iscsi_bhs_data_out
*reqh
;
4220 struct spdk_scsi_lun
*lun_dev
;
4221 uint32_t transfer_tag
;
4223 uint32_t transfer_len
;
4225 uint32_t buffer_offset
;
4229 int reject_reason
= ISCSI_REASON_INVALID_PDU_FIELD
;
4231 if (conn
->sess
->session_type
== SESSION_TYPE_DISCOVERY
) {
4232 SPDK_ERRLOG("ISCSI_OP_SCSI_DATAOUT not allowed in discovery session\n");
4233 return SPDK_ISCSI_CONNECTION_FATAL
;
4236 reqh
= (struct iscsi_bhs_data_out
*)&pdu
->bhs
;
4237 F_bit
= !!(reqh
->flags
& ISCSI_FLAG_FINAL
);
4238 transfer_tag
= from_be32(&reqh
->ttt
);
4239 task_tag
= from_be32(&reqh
->itt
);
4240 DataSN
= from_be32(&reqh
->data_sn
);
4241 buffer_offset
= from_be32(&reqh
->buffer_offset
);
4243 task
= get_transfer_task(conn
, transfer_tag
);
4245 SPDK_ERRLOG("Not found task for transfer_tag=%x\n", transfer_tag
);
4249 lun_dev
= spdk_scsi_dev_get_lun(conn
->dev
, task
->lun_id
);
4251 if (pdu
->data_segment_len
> task
->desired_data_transfer_length
) {
4252 SPDK_ERRLOG("the dataout pdu data length is larger than the value sent by R2T PDU\n");
4253 return SPDK_ISCSI_CONNECTION_FATAL
;
4256 if (task
->tag
!= task_tag
) {
4257 SPDK_ERRLOG("The r2t task tag is %u, and the dataout task tag is %u\n",
4258 task
->tag
, task_tag
);
4262 if (DataSN
!= task
->r2t_datasn
) {
4263 SPDK_ERRLOG("DataSN(%u) exp=%d error\n", DataSN
, task
->r2t_datasn
);
4264 if (conn
->sess
->ErrorRecoveryLevel
>= 1) {
4265 goto send_r2t_recovery_return
;
4267 reject_reason
= ISCSI_REASON_PROTOCOL_ERROR
;
4272 if (buffer_offset
!= task
->next_expected_r2t_offset
) {
4273 SPDK_ERRLOG("offset(%u) error\n", buffer_offset
);
4274 return SPDK_ISCSI_CONNECTION_FATAL
;
4277 transfer_len
= task
->scsi
.transfer_len
;
4278 task
->current_r2t_length
+= pdu
->data_segment_len
;
4279 task
->next_expected_r2t_offset
+= pdu
->data_segment_len
;
4282 if (task
->current_r2t_length
> conn
->sess
->MaxBurstLength
) {
4283 SPDK_ERRLOG("R2T burst(%u) > MaxBurstLength(%u)\n",
4284 task
->current_r2t_length
,
4285 conn
->sess
->MaxBurstLength
);
4286 return SPDK_ISCSI_CONNECTION_FATAL
;
4291 * This R2T burst is done. Clear the length before we
4292 * receive a PDU for the next R2T burst.
4294 task
->current_r2t_length
= 0;
4297 subtask
= spdk_iscsi_task_get(conn
, task
, spdk_iscsi_task_cpl
);
4298 if (subtask
== NULL
) {
4299 SPDK_ERRLOG("Unable to acquire subtask\n");
4300 return SPDK_ISCSI_CONNECTION_FATAL
;
4302 subtask
->scsi
.offset
= buffer_offset
;
4303 subtask
->scsi
.length
= pdu
->data_segment_len
;
4304 if (spdk_likely(!pdu
->dif_insert_or_strip
)) {
4305 spdk_scsi_task_set_data(&subtask
->scsi
, pdu
->data
, pdu
->data_segment_len
);
4307 spdk_scsi_task_set_data(&subtask
->scsi
, pdu
->data
, pdu
->data_buf_len
);
4309 spdk_iscsi_task_associate_pdu(subtask
, pdu
);
4311 if (task
->next_expected_r2t_offset
== transfer_len
) {
4312 task
->acked_r2tsn
++;
4313 } else if (F_bit
&& (task
->next_r2t_offset
< transfer_len
)) {
4314 task
->acked_r2tsn
++;
4315 len
= DMIN32(conn
->sess
->MaxBurstLength
, (transfer_len
-
4316 task
->next_r2t_offset
));
4317 rc
= iscsi_send_r2t(conn
, task
, task
->next_r2t_offset
, len
,
4318 task
->ttt
, &task
->R2TSN
);
4320 SPDK_ERRLOG("iscsi_send_r2t() failed\n");
4322 task
->next_r2t_offset
+= len
;
4325 if (lun_dev
== NULL
) {
4326 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "LUN %d is removed, complete the task immediately\n",
4328 subtask
->scsi
.transfer_len
= subtask
->scsi
.length
;
4329 spdk_scsi_task_process_null_lun(&subtask
->scsi
);
4330 spdk_iscsi_task_cpl(&subtask
->scsi
);
4334 iscsi_queue_task(conn
, subtask
);
4337 send_r2t_recovery_return
:
4338 rc
= iscsi_send_r2t_recovery(conn
, task
, task
->acked_r2tsn
, true);
4344 return iscsi_reject(conn
, pdu
, reject_reason
);
4348 iscsi_send_r2t(struct spdk_iscsi_conn
*conn
,
4349 struct spdk_iscsi_task
*task
, int offset
,
4350 int len
, uint32_t transfer_tag
, uint32_t *R2TSN
)
4352 struct spdk_iscsi_pdu
*rsp_pdu
;
4353 struct iscsi_bhs_r2t
*rsph
;
4357 rsp_pdu
= spdk_get_pdu();
4358 if (rsp_pdu
== NULL
) {
4359 return SPDK_ISCSI_CONNECTION_FATAL
;
4361 rsph
= (struct iscsi_bhs_r2t
*)&rsp_pdu
->bhs
;
4362 rsp_pdu
->data
= NULL
;
4363 rsph
->opcode
= ISCSI_OP_R2T
;
4364 rsph
->flags
|= 0x80; /* bit 0 is default to 1 */
4365 fmt_lun
= spdk_scsi_lun_id_int_to_fmt(task
->lun_id
);
4366 to_be64(&rsph
->lun
, fmt_lun
);
4367 to_be32(&rsph
->itt
, task
->tag
);
4368 to_be32(&rsph
->ttt
, transfer_tag
);
4370 to_be32(&rsph
->stat_sn
, conn
->StatSN
);
4371 to_be32(&rsph
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
4372 to_be32(&rsph
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
4374 to_be32(&rsph
->r2t_sn
, *R2TSN
);
4377 task
->r2t_datasn
= 0; /* next expected datasn to ack */
4379 to_be32(&rsph
->buffer_offset
, (uint32_t)offset
);
4380 to_be32(&rsph
->desired_xfer_len
, (uint32_t)len
);
4381 task
->desired_data_transfer_length
= (size_t)len
;
4383 /* we need to hold onto this task/cmd because until the PDU has been
4385 rsp_pdu
->task
= task
;
4388 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
4393 void spdk_iscsi_send_nopin(struct spdk_iscsi_conn
*conn
)
4395 struct spdk_iscsi_pdu
*rsp_pdu
;
4396 struct iscsi_bhs_nop_in
*rsp
;
4398 /* Only send nopin if we have logged in and are in a normal session. */
4399 if (conn
->sess
== NULL
||
4400 !conn
->full_feature
||
4401 !spdk_iscsi_param_eq_val(conn
->sess
->params
, "SessionType", "Normal")) {
4405 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "send NOPIN isid=%"PRIx64
", tsih=%u, cid=%u\n",
4406 conn
->sess
->isid
, conn
->sess
->tsih
, conn
->cid
);
4407 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
4408 conn
->StatSN
, conn
->sess
->ExpCmdSN
,
4409 conn
->sess
->MaxCmdSN
);
4411 rsp_pdu
= spdk_get_pdu();
4412 rsp
= (struct iscsi_bhs_nop_in
*) &rsp_pdu
->bhs
;
4413 rsp_pdu
->data
= NULL
;
4416 * spdk_get_pdu() memset's the PDU for us, so only fill out the needed
4419 rsp
->opcode
= ISCSI_OP_NOPIN
;
4422 * Technically the to_be32() is not needed here, since
4423 * to_be32(0xFFFFFFFU) returns 0xFFFFFFFFU.
4425 to_be32(&rsp
->itt
, 0xFFFFFFFFU
);
4426 to_be32(&rsp
->ttt
, conn
->id
);
4427 to_be32(&rsp
->stat_sn
, conn
->StatSN
);
4428 to_be32(&rsp
->exp_cmd_sn
, conn
->sess
->ExpCmdSN
);
4429 to_be32(&rsp
->max_cmd_sn
, conn
->sess
->MaxCmdSN
);
4431 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
4432 conn
->last_nopin
= spdk_get_ticks();
4433 conn
->nop_outstanding
= true;
4437 init_login_reject_response(struct spdk_iscsi_pdu
*pdu
, struct spdk_iscsi_pdu
*rsp_pdu
)
4439 struct iscsi_bhs_login_rsp
*rsph
;
4441 memset(rsp_pdu
, 0, sizeof(struct spdk_iscsi_pdu
));
4442 rsph
= (struct iscsi_bhs_login_rsp
*)&rsp_pdu
->bhs
;
4443 rsph
->version_max
= ISCSI_VERSION
;
4444 rsph
->version_act
= ISCSI_VERSION
;
4445 rsph
->opcode
= ISCSI_OP_LOGIN_RSP
;
4446 rsph
->status_class
= ISCSI_CLASS_INITIATOR_ERROR
;
4447 rsph
->status_detail
= ISCSI_LOGIN_INVALID_LOGIN_REQUEST
;
4448 rsph
->itt
= pdu
->bhs
.itt
;
4452 iscsi_pdu_dump(struct spdk_iscsi_pdu
*pdu
)
4454 SPDK_ERRLOGDUMP("PDU", (uint8_t *)&pdu
->bhs
, ISCSI_BHS_LEN
);
4458 spdk_iscsi_execute(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
)
4462 struct spdk_iscsi_pdu
*rsp_pdu
= NULL
;
4465 struct spdk_iscsi_sess
*sess
;
4466 struct iscsi_bhs_scsi_req
*reqh
;
4472 opcode
= pdu
->bhs
.opcode
;
4473 reqh
= (struct iscsi_bhs_scsi_req
*)&pdu
->bhs
;
4474 pdu
->cmd_sn
= from_be32(&reqh
->cmd_sn
);
4476 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "opcode %x\n", opcode
);
4478 if (opcode
== ISCSI_OP_LOGIN
) {
4479 rc
= iscsi_op_login(conn
, pdu
);
4481 SPDK_ERRLOG("iscsi_op_login() failed\n");
4486 /* connection in login phase but receive non-login opcode
4487 * return response code 0x020b to initiator.
4489 if (!conn
->full_feature
&& conn
->state
== ISCSI_CONN_STATE_RUNNING
) {
4490 rsp_pdu
= spdk_get_pdu();
4491 if (rsp_pdu
== NULL
) {
4492 return SPDK_ISCSI_CONNECTION_FATAL
;
4494 init_login_reject_response(pdu
, rsp_pdu
);
4495 spdk_iscsi_conn_write_pdu(conn
, rsp_pdu
);
4496 SPDK_ERRLOG("Received opcode %d in login phase\n", opcode
);
4497 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE
;
4498 } else if (conn
->state
== ISCSI_CONN_STATE_INVALID
) {
4499 SPDK_ERRLOG("before Full Feature\n");
4500 iscsi_pdu_dump(pdu
);
4501 return SPDK_ISCSI_CONNECTION_FATAL
;
4506 SPDK_ERRLOG("Connection has no associated session!\n");
4507 return SPDK_ISCSI_CONNECTION_FATAL
;
4509 I_bit
= reqh
->immediate
;
4511 if (SN32_LT(pdu
->cmd_sn
, sess
->ExpCmdSN
) ||
4512 SN32_GT(pdu
->cmd_sn
, sess
->MaxCmdSN
)) {
4513 if (sess
->session_type
== SESSION_TYPE_NORMAL
&&
4514 opcode
!= ISCSI_OP_SCSI_DATAOUT
) {
4515 SPDK_ERRLOG("CmdSN(%u) ignore (ExpCmdSN=%u, MaxCmdSN=%u)\n",
4516 pdu
->cmd_sn
, sess
->ExpCmdSN
, sess
->MaxCmdSN
);
4518 if (sess
->ErrorRecoveryLevel
>= 1) {
4519 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Skip the error in ERL 1 and 2\n");
4521 return SPDK_PDU_FATAL
;
4525 } else if (pdu
->cmd_sn
!= sess
->ExpCmdSN
) {
4526 SPDK_ERRLOG("CmdSN(%u) error ExpCmdSN=%u\n", pdu
->cmd_sn
, sess
->ExpCmdSN
);
4528 if (sess
->ErrorRecoveryLevel
>= 1) {
4529 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Skip the error in ERL 1 and 2\n");
4530 } else if (opcode
!= ISCSI_OP_NOPOUT
) {
4532 * The Linux initiator does not send valid CmdSNs for
4533 * nopout under heavy load, so do not close the
4534 * connection in that case.
4536 return SPDK_ISCSI_CONNECTION_FATAL
;
4540 ExpStatSN
= from_be32(&reqh
->exp_stat_sn
);
4541 if (SN32_GT(ExpStatSN
, conn
->StatSN
)) {
4542 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "StatSN(%u) advanced\n", ExpStatSN
);
4543 ExpStatSN
= conn
->StatSN
;
4546 if (sess
->ErrorRecoveryLevel
>= 1) {
4547 remove_acked_pdu(conn
, ExpStatSN
);
4550 if (!I_bit
&& opcode
!= ISCSI_OP_SCSI_DATAOUT
) {
4555 case ISCSI_OP_NOPOUT
:
4556 rc
= iscsi_op_nopout(conn
, pdu
);
4558 SPDK_ERRLOG("spdk_iscsi_op_nopout() failed\n");
4564 rc
= iscsi_op_scsi(conn
, pdu
);
4566 SPDK_ERRLOG("spdk_iscsi_op_scsi() failed\n");
4571 rc
= iscsi_op_task(conn
, pdu
);
4573 SPDK_ERRLOG("spdk_iscsi_op_task() failed\n");
4579 rc
= iscsi_op_text(conn
, pdu
);
4581 SPDK_ERRLOG("spdk_iscsi_op_text() failed\n");
4586 case ISCSI_OP_LOGOUT
:
4587 rc
= iscsi_op_logout(conn
, pdu
);
4589 SPDK_ERRLOG("spdk_iscsi_op_logout() failed\n");
4594 case ISCSI_OP_SCSI_DATAOUT
:
4595 rc
= iscsi_op_data(conn
, pdu
);
4597 SPDK_ERRLOG("spdk_iscsi_op_data() failed\n");
4602 case ISCSI_OP_SNACK
:
4603 rc
= iscsi_op_snack(conn
, pdu
);
4605 SPDK_ERRLOG("spdk_iscsi_op_snack() failed\n");
4611 SPDK_ERRLOG("unsupported opcode %x\n", opcode
);
4612 return iscsi_reject(conn
, pdu
, ISCSI_REASON_PROTOCOL_ERROR
);
4619 spdk_iscsi_get_dif_ctx(struct spdk_iscsi_conn
*conn
, struct spdk_iscsi_pdu
*pdu
,
4620 struct spdk_dif_ctx
*dif_ctx
)
4622 struct iscsi_bhs
*bhs
;
4623 uint32_t data_offset
= 0;
4624 uint8_t *cdb
= NULL
;
4627 struct spdk_scsi_lun
*lun_dev
;
4629 /* connection is not in full feature phase but non-login opcode
4632 if ((!conn
->full_feature
&& conn
->state
== ISCSI_CONN_STATE_RUNNING
) ||
4633 conn
->state
== ISCSI_CONN_STATE_INVALID
) {
4637 /* SCSI Command is allowed only in normal session */
4638 if (conn
->sess
== NULL
||
4639 conn
->sess
->session_type
!= SESSION_TYPE_NORMAL
) {
4645 switch (bhs
->opcode
) {
4646 case ISCSI_OP_SCSI
: {
4647 struct iscsi_bhs_scsi_req
*sbhs
;
4649 sbhs
= (struct iscsi_bhs_scsi_req
*)bhs
;
4652 lun
= from_be64(&sbhs
->lun
);
4653 lun_id
= spdk_scsi_lun_id_fmt_to_int(lun
);
4656 case ISCSI_OP_SCSI_DATAOUT
: {
4657 struct iscsi_bhs_data_out
*dbhs
;
4658 struct spdk_iscsi_task
*task
;
4661 dbhs
= (struct iscsi_bhs_data_out
*)bhs
;
4662 data_offset
= from_be32(&dbhs
->buffer_offset
);
4663 transfer_tag
= from_be32(&dbhs
->ttt
);
4664 task
= get_transfer_task(conn
, transfer_tag
);
4668 cdb
= task
->scsi
.cdb
;
4669 lun_id
= task
->lun_id
;
4672 case ISCSI_OP_SCSI_DATAIN
: {
4673 struct iscsi_bhs_data_in
*dbhs
;
4674 struct spdk_iscsi_task
*task
;
4676 dbhs
= (struct iscsi_bhs_data_in
*)bhs
;
4677 data_offset
= from_be32(&dbhs
->buffer_offset
);
4679 assert(task
!= NULL
);
4680 cdb
= task
->scsi
.cdb
;
4681 lun_id
= task
->lun_id
;
4688 lun_dev
= spdk_scsi_dev_get_lun(conn
->dev
, lun_id
);
4689 if (lun_dev
== NULL
) {
4693 return spdk_scsi_lun_get_dif_ctx(lun_dev
, cdb
, data_offset
, dif_ctx
);
4696 void spdk_free_sess(struct spdk_iscsi_sess
*sess
)
4703 sess
->target
= NULL
;
4704 sess
->session_type
= SESSION_TYPE_INVALID
;
4705 spdk_iscsi_param_free(sess
->params
);
4707 spdk_scsi_port_free(&sess
->initiator_port
);
4708 spdk_mempool_put(g_spdk_iscsi
.session_pool
, (void *)sess
);
4712 create_iscsi_sess(struct spdk_iscsi_conn
*conn
,
4713 struct spdk_iscsi_tgt_node
*target
,
4714 enum session_type session_type
)
4716 struct spdk_iscsi_sess
*sess
;
4719 sess
= spdk_mempool_get(g_spdk_iscsi
.session_pool
);
4721 SPDK_ERRLOG("Unable to get session object\n");
4722 SPDK_ERRLOG("MaxSessions set to %d\n", g_spdk_iscsi
.MaxSessions
);
4726 /* configuration values */
4727 pthread_mutex_lock(&g_spdk_iscsi
.mutex
);
4729 sess
->MaxConnections
= g_spdk_iscsi
.MaxConnectionsPerSession
;
4730 sess
->MaxOutstandingR2T
= DEFAULT_MAXOUTSTANDINGR2T
;
4732 sess
->DefaultTime2Wait
= g_spdk_iscsi
.DefaultTime2Wait
;
4733 sess
->DefaultTime2Retain
= g_spdk_iscsi
.DefaultTime2Retain
;
4734 sess
->FirstBurstLength
= g_spdk_iscsi
.FirstBurstLength
;
4735 sess
->MaxBurstLength
= SPDK_ISCSI_MAX_BURST_LENGTH
;
4736 sess
->InitialR2T
= DEFAULT_INITIALR2T
;
4737 sess
->ImmediateData
= g_spdk_iscsi
.ImmediateData
;
4738 sess
->DataPDUInOrder
= DEFAULT_DATAPDUINORDER
;
4739 sess
->DataSequenceInOrder
= DEFAULT_DATASEQUENCEINORDER
;
4740 sess
->ErrorRecoveryLevel
= g_spdk_iscsi
.ErrorRecoveryLevel
;
4742 pthread_mutex_unlock(&g_spdk_iscsi
.mutex
);
4744 sess
->tag
= conn
->portal
->group
->tag
;
4746 sess
->conns
= calloc(sess
->MaxConnections
, sizeof(*sess
->conns
));
4748 SPDK_ERRLOG("calloc() failed for connection array\n");
4752 sess
->connections
= 0;
4754 sess
->conns
[sess
->connections
] = conn
;
4755 sess
->connections
++;
4757 sess
->params
= NULL
;
4758 sess
->target
= target
;
4760 sess
->session_type
= session_type
;
4761 sess
->current_text_itt
= 0xffffffffU
;
4763 /* set default params */
4764 rc
= spdk_iscsi_sess_params_init(&sess
->params
);
4766 SPDK_ERRLOG("iscsi_sess_params_init() failed\n");
4769 /* replace with config value */
4770 rc
= spdk_iscsi_param_set_int(sess
->params
, "MaxConnections",
4771 sess
->MaxConnections
);
4773 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4777 rc
= spdk_iscsi_param_set_int(sess
->params
, "MaxOutstandingR2T",
4778 sess
->MaxOutstandingR2T
);
4780 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4784 rc
= spdk_iscsi_param_set_int(sess
->params
, "DefaultTime2Wait",
4785 sess
->DefaultTime2Wait
);
4787 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4791 rc
= spdk_iscsi_param_set_int(sess
->params
, "DefaultTime2Retain",
4792 sess
->DefaultTime2Retain
);
4794 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4798 rc
= spdk_iscsi_param_set_int(sess
->params
, "FirstBurstLength",
4799 sess
->FirstBurstLength
);
4801 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4805 rc
= spdk_iscsi_param_set_int(sess
->params
, "MaxBurstLength",
4806 sess
->MaxBurstLength
);
4808 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4812 rc
= spdk_iscsi_param_set(sess
->params
, "InitialR2T",
4813 sess
->InitialR2T
? "Yes" : "No");
4815 SPDK_ERRLOG("iscsi_param_set() failed\n");
4819 rc
= spdk_iscsi_param_set(sess
->params
, "ImmediateData",
4820 sess
->ImmediateData
? "Yes" : "No");
4822 SPDK_ERRLOG("iscsi_param_set() failed\n");
4826 rc
= spdk_iscsi_param_set(sess
->params
, "DataPDUInOrder",
4827 sess
->DataPDUInOrder
? "Yes" : "No");
4829 SPDK_ERRLOG("iscsi_param_set() failed\n");
4833 rc
= spdk_iscsi_param_set(sess
->params
, "DataSequenceInOrder",
4834 sess
->DataSequenceInOrder
? "Yes" : "No");
4836 SPDK_ERRLOG("iscsi_param_set() failed\n");
4840 rc
= spdk_iscsi_param_set_int(sess
->params
, "ErrorRecoveryLevel",
4841 sess
->ErrorRecoveryLevel
);
4843 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4847 /* realloc buffer */
4848 rc
= spdk_iscsi_param_set_int(conn
->params
, "MaxRecvDataSegmentLength",
4849 conn
->MaxRecvDataSegmentLength
);
4851 SPDK_ERRLOG("iscsi_param_set_int() failed\n");
4855 /* sess for first connection of session */
4860 spdk_free_sess(sess
);
4865 static struct spdk_iscsi_sess
*
4866 get_iscsi_sess_by_tsih(uint16_t tsih
)
4868 struct spdk_iscsi_sess
*session
;
4870 if (tsih
== 0 || tsih
> g_spdk_iscsi
.MaxSessions
) {
4874 session
= g_spdk_iscsi
.session
[tsih
- 1];
4875 assert(tsih
== session
->tsih
);
4881 append_iscsi_sess(struct spdk_iscsi_conn
*conn
,
4882 const char *initiator_port_name
, uint16_t tsih
, uint16_t cid
)
4884 struct spdk_iscsi_sess
*sess
;
4886 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "append session: init port name=%s, tsih=%u, cid=%u\n",
4887 initiator_port_name
, tsih
, cid
);
4889 sess
= get_iscsi_sess_by_tsih(tsih
);
4891 SPDK_ERRLOG("spdk_get_iscsi_sess_by_tsih failed\n");
4892 return ISCSI_LOGIN_CONN_ADD_FAIL
;
4894 if ((conn
->portal
->group
->tag
!= sess
->tag
) ||
4895 (strcasecmp(initiator_port_name
, spdk_scsi_port_get_name(sess
->initiator_port
)) != 0) ||
4896 (conn
->target
!= sess
->target
)) {
4898 SPDK_ERRLOG("no MCS session for init port name=%s, tsih=%d, cid=%d\n",
4899 initiator_port_name
, tsih
, cid
);
4900 return ISCSI_LOGIN_CONN_ADD_FAIL
;
4903 if (sess
->connections
>= sess
->MaxConnections
) {
4904 /* no slot for connection */
4905 SPDK_ERRLOG("too many connections for init port name=%s, tsih=%d, cid=%d\n",
4906 initiator_port_name
, tsih
, cid
);
4907 return ISCSI_LOGIN_TOO_MANY_CONNECTIONS
;
4910 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Connections (tsih %d): %d\n", sess
->tsih
, sess
->connections
);
4914 * TODO: need a mutex or other sync mechanism to protect the session's
4917 sess
->conns
[sess
->connections
] = conn
;
4918 sess
->connections
++;
4923 bool spdk_iscsi_is_deferred_free_pdu(struct spdk_iscsi_pdu
*pdu
)
4929 if (pdu
->bhs
.opcode
== ISCSI_OP_R2T
||
4930 pdu
->bhs
.opcode
== ISCSI_OP_SCSI_DATAIN
) {