1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 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 17 * distribution. 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. 21 * 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. 33 */ 34 35 #include "spdk/stdinc.h" 36 37 #include <rte_config.h> 38 #include <rte_mempool.h> 39 40 #include "spdk/crc32.h" 41 #include "spdk/endian.h" 42 #include "spdk/env.h" 43 #include "spdk/trace.h" 44 #include "spdk/string.h" 45 #include "spdk/queue.h" 46 #include "spdk/conf.h" 47 #include "spdk/net.h" 48 49 #include "iscsi/md5.h" 50 #include "iscsi/iscsi.h" 51 #include "iscsi/param.h" 52 #include "iscsi/tgt_node.h" 53 #include "iscsi/task.h" 54 #include "iscsi/conn.h" 55 #include "spdk/scsi.h" 56 #include "spdk/bdev.h" 57 #include "iscsi/portal_grp.h" 58 #include "iscsi/acceptor.h" 59 60 #include "spdk_internal/log.h" 61 62 #define MAX_TMPBUF 1024 63 64 #define SPDK_CRC32C_INITIAL 0xffffffffUL 65 #define SPDK_CRC32C_XOR 0xffffffffUL 66 67 #ifdef __FreeBSD__ 68 #define HAVE_SRANDOMDEV 1 69 #define HAVE_ARC4RANDOM 1 70 #endif 71 72 struct spdk_iscsi_globals g_spdk_iscsi; 73 74 /* random value generation */ 75 static void spdk_gen_random(uint8_t *buf, size_t len); 76 #ifndef HAVE_SRANDOMDEV 77 static void srandomdev(void); 78 #endif /* HAVE_SRANDOMDEV */ 79 #ifndef HAVE_ARC4RANDOM 80 //static uint32_t arc4random(void); 81 #endif /* HAVE_ARC4RANDOM */ 82 83 /* convert from/to bin/hex */ 84 static int spdk_bin2hex(char *buf, size_t len, const uint8_t *data, size_t data_len); 85 static int spdk_hex2bin(uint8_t *data, size_t data_len, const char *str); 86 87 88 static int spdk_add_transfer_task(struct spdk_iscsi_conn *conn, 89 struct spdk_iscsi_task *task); 90 static int 91 spdk_iscsi_send_r2t(struct spdk_iscsi_conn *conn, 92 struct spdk_iscsi_task *task, int offset, 93 int len, uint32_t transfer_tag, uint32_t *R2TSN); 94 static int 95 spdk_create_iscsi_sess(struct spdk_iscsi_conn *conn, 96 struct spdk_iscsi_tgt_node *target, 97 enum session_type session_type); 98 static int 99 spdk_append_iscsi_sess(struct spdk_iscsi_conn *conn, 100 const char *initiator_port_name, uint16_t tsih, uint16_t cid); 101 static int 102 spdk_iscsi_send_r2t_recovery(struct spdk_iscsi_conn *conn, 103 struct spdk_iscsi_task *r2t_task, uint32_t r2t_sn, 104 bool send_new_r2tsn); 105 static void 106 spdk_remove_acked_pdu(struct spdk_iscsi_conn *conn, 107 uint32_t ExpStatSN); 108 109 static int 110 spdk_iscsi_reject(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu, 111 int reason); 112 113 #define DMIN32(A,B) ((uint32_t) ((uint32_t)(A) > (uint32_t)(B) ? (uint32_t)(B) : (uint32_t)(A))) 114 #define DMIN64(A,B) ((uint64_t) ((A) > (B) ? (B) : (A))) 115 116 #define MATCH_DIGEST_WORD(BUF, CRC32C) \ 117 ( ((((uint32_t) *((uint8_t *)(BUF)+0)) << 0) \ 118 | (((uint32_t) *((uint8_t *)(BUF)+1)) << 8) \ 119 | (((uint32_t) *((uint8_t *)(BUF)+2)) << 16) \ 120 | (((uint32_t) *((uint8_t *)(BUF)+3)) << 24)) \ 121 == (CRC32C)) 122 123 #define MAKE_DIGEST_WORD(BUF, CRC32C) \ 124 ( ((*((uint8_t *)(BUF)+0)) = (uint8_t)((uint32_t)(CRC32C) >> 0)), \ 125 ((*((uint8_t *)(BUF)+1)) = (uint8_t)((uint32_t)(CRC32C) >> 8)), \ 126 ((*((uint8_t *)(BUF)+2)) = (uint8_t)((uint32_t)(CRC32C) >> 16)), \ 127 ((*((uint8_t *)(BUF)+3)) = (uint8_t)((uint32_t)(CRC32C) >> 24))) 128 129 #if 0 130 static int 131 spdk_match_digest_word(const uint8_t *buf, uint32_t crc32c) 132 { 133 uint32_t l; 134 135 l = (buf[0] & 0xffU) << 0; 136 l |= (buf[1] & 0xffU) << 8; 137 l |= (buf[2] & 0xffU) << 16; 138 l |= (buf[3] & 0xffU) << 24; 139 return (l == crc32c); 140 } 141 142 static uint8_t * 143 spdk_make_digest_word(uint8_t *buf, size_t len, uint32_t crc32c) 144 { 145 if (len < ISCSI_DIGEST_LEN) 146 return NULL; 147 148 buf[0] = (crc32c >> 0) & 0xffU; 149 buf[1] = (crc32c >> 8) & 0xffU; 150 buf[2] = (crc32c >> 16) & 0xffU; 151 buf[3] = (crc32c >> 24) & 0xffU; 152 return buf; 153 } 154 #endif 155 156 #ifndef HAVE_SRANDOMDEV 157 static void 158 srandomdev(void) 159 { 160 unsigned long seed; 161 time_t now; 162 pid_t pid; 163 164 pid = getpid(); 165 now = time(NULL); 166 seed = pid ^ now; 167 srandom(seed); 168 } 169 #endif /* HAVE_SRANDOMDEV */ 170 171 #ifndef HAVE_ARC4RANDOM 172 static int spdk_arc4random_initialized = 0; 173 174 static uint32_t 175 arc4random(void) 176 { 177 uint32_t r; 178 uint32_t r1, r2; 179 180 if (!spdk_arc4random_initialized) { 181 srandomdev(); 182 spdk_arc4random_initialized = 1; 183 } 184 r1 = (uint32_t)(random() & 0xffff); 185 r2 = (uint32_t)(random() & 0xffff); 186 r = (r1 << 16) | r2; 187 return r; 188 } 189 #endif /* HAVE_ARC4RANDOM */ 190 191 static void 192 spdk_gen_random(uint8_t *buf, size_t len) 193 { 194 #ifdef USE_RANDOM 195 long l; 196 size_t idx; 197 198 srandomdev(); 199 for (idx = 0; idx < len; idx++) { 200 l = random(); 201 buf[idx] = (uint8_t) l; 202 } 203 #else 204 uint32_t r; 205 size_t idx; 206 207 for (idx = 0; idx < len; idx++) { 208 r = arc4random(); 209 buf[idx] = (uint8_t) r; 210 } 211 #endif /* USE_RANDOM */ 212 } 213 214 static uint64_t 215 spdk_iscsi_get_isid(const uint8_t isid[6]) 216 { 217 return (uint64_t)isid[0] << 40 | 218 (uint64_t)isid[1] << 32 | 219 (uint64_t)isid[2] << 24 | 220 (uint64_t)isid[3] << 16 | 221 (uint64_t)isid[4] << 8 | 222 (uint64_t)isid[5]; 223 } 224 225 static int 226 spdk_bin2hex(char *buf, size_t len, const uint8_t *data, size_t data_len) 227 { 228 const char *digits = "0123456789ABCDEF"; 229 size_t total = 0; 230 size_t idx; 231 232 if (len < 3) 233 return -1; 234 buf[total] = '0'; 235 total++; 236 buf[total] = 'x'; 237 total++; 238 buf[total] = '\0'; 239 240 for (idx = 0; idx < data_len; idx++) { 241 if (total + 3 > len) { 242 buf[total] = '\0'; 243 return - 1; 244 } 245 buf[total] = digits[(data[idx] >> 4) & 0x0fU]; 246 total++; 247 buf[total] = digits[data[idx] & 0x0fU]; 248 total++; 249 } 250 buf[total] = '\0'; 251 return total; 252 } 253 254 static int 255 spdk_hex2bin(uint8_t *data, size_t data_len, const char *str) 256 { 257 const char *digits = "0123456789ABCDEF"; 258 const char *dp; 259 const char *p; 260 size_t total = 0; 261 int n0, n1; 262 263 p = str; 264 if (p[0] != '0' && (p[1] != 'x' && p[1] != 'X')) 265 return -1; 266 p += 2; 267 268 while (p[0] != '\0' && p[1] != '\0') { 269 if (total >= data_len) { 270 return -1; 271 } 272 dp = strchr(digits, toupper((int) p[0])); 273 if (dp == NULL) { 274 return -1; 275 } 276 n0 = (int)(dp - digits); 277 dp = strchr(digits, toupper((int) p[1])); 278 if (dp == NULL) { 279 return -1; 280 } 281 n1 = (int)(dp - digits); 282 283 data[total] = (uint8_t)(((n0 & 0x0fU) << 4) | (n1 & 0x0fU)); 284 total++; 285 p += 2; 286 } 287 return total; 288 } 289 290 static int 291 spdk_islun2lun(uint64_t islun) 292 { 293 uint64_t fmt_lun; 294 uint64_t method; 295 int lun_i; 296 297 fmt_lun = islun; 298 method = (fmt_lun >> 62) & 0x03U; 299 fmt_lun = fmt_lun >> 48; 300 if (method == 0x00U) { 301 lun_i = (int)(fmt_lun & 0x00ffU); 302 } else if (method == 0x01U) { 303 lun_i = (int)(fmt_lun & 0x3fffU); 304 } else { 305 lun_i = 0xffffU; 306 } 307 return lun_i; 308 } 309 310 static uint32_t 311 spdk_iscsi_pdu_calc_header_digest(struct spdk_iscsi_pdu *pdu) 312 { 313 uint32_t crc32c; 314 uint32_t ahs_len_bytes = pdu->bhs.total_ahs_len * 4; 315 316 crc32c = SPDK_CRC32C_INITIAL; 317 crc32c = spdk_crc32c_update(&pdu->bhs, ISCSI_BHS_LEN, crc32c); 318 319 if (ahs_len_bytes) { 320 crc32c = spdk_crc32c_update(pdu->ahs, ahs_len_bytes, crc32c); 321 } 322 323 /* BHS and AHS are always 4-byte multiples in length, so no padding is necessary. */ 324 crc32c = crc32c ^ SPDK_CRC32C_XOR; 325 return crc32c; 326 } 327 328 static uint32_t 329 spdk_iscsi_pdu_calc_data_digest(struct spdk_iscsi_pdu *pdu) 330 { 331 uint32_t data_len = DGET24(pdu->bhs.data_segment_len); 332 uint32_t crc32c; 333 uint32_t mod; 334 335 crc32c = SPDK_CRC32C_INITIAL; 336 crc32c = spdk_crc32c_update(pdu->data, data_len, crc32c); 337 338 mod = data_len % ISCSI_ALIGNMENT; 339 if (mod != 0) { 340 uint32_t pad_length = ISCSI_ALIGNMENT - mod; 341 uint8_t pad[3] = {0, 0, 0}; 342 343 assert(pad_length > 0); 344 assert(pad_length <= sizeof(pad)); 345 crc32c = spdk_crc32c_update(pad, pad_length, crc32c); 346 } 347 348 crc32c = crc32c ^ SPDK_CRC32C_XOR; 349 return crc32c; 350 } 351 352 int 353 spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu) 354 { 355 struct spdk_iscsi_pdu *pdu; 356 struct rte_mempool *pool; 357 uint32_t crc32c; 358 int ahs_len; 359 int data_len; 360 int max_segment_len; 361 int rc; 362 363 if (conn->pdu_in_progress == NULL) { 364 conn->pdu_in_progress = spdk_get_pdu(); 365 } 366 367 pdu = conn->pdu_in_progress; 368 369 if (pdu->bhs_valid_bytes < ISCSI_BHS_LEN) { 370 rc = spdk_iscsi_conn_read_data(conn, 371 ISCSI_BHS_LEN - pdu->bhs_valid_bytes, 372 (uint8_t *)&pdu->bhs + pdu->bhs_valid_bytes); 373 if (rc < 0) { 374 *_pdu = NULL; 375 spdk_put_pdu(pdu); 376 conn->pdu_in_progress = NULL; 377 return rc; 378 } 379 pdu->bhs_valid_bytes += rc; 380 if (pdu->bhs_valid_bytes < ISCSI_BHS_LEN) { 381 *_pdu = NULL; 382 return SPDK_SUCCESS; 383 } 384 } 385 386 data_len = ISCSI_ALIGN(DGET24(pdu->bhs.data_segment_len)); 387 388 /* AHS */ 389 ahs_len = pdu->bhs.total_ahs_len * 4; 390 assert(ahs_len <= ISCSI_AHS_LEN); 391 if (pdu->ahs_valid_bytes < ahs_len) { 392 rc = spdk_iscsi_conn_read_data(conn, 393 ahs_len - pdu->ahs_valid_bytes, 394 pdu->ahs + pdu->ahs_valid_bytes); 395 if (rc < 0) { 396 *_pdu = NULL; 397 spdk_put_pdu(pdu); 398 conn->pdu_in_progress = NULL; 399 return rc; 400 } 401 402 pdu->ahs_valid_bytes += rc; 403 if (pdu->ahs_valid_bytes < ahs_len) { 404 *_pdu = NULL; 405 return SPDK_SUCCESS; 406 } 407 } 408 409 /* Header Digest */ 410 if (conn->header_digest && 411 pdu->hdigest_valid_bytes < ISCSI_DIGEST_LEN) { 412 rc = spdk_iscsi_conn_read_data(conn, 413 ISCSI_DIGEST_LEN - pdu->hdigest_valid_bytes, 414 pdu->header_digest + pdu->hdigest_valid_bytes); 415 if (rc < 0) { 416 *_pdu = NULL; 417 spdk_put_pdu(pdu); 418 conn->pdu_in_progress = NULL; 419 return rc; 420 } 421 422 pdu->hdigest_valid_bytes += rc; 423 if (pdu->hdigest_valid_bytes < ISCSI_DIGEST_LEN) { 424 *_pdu = NULL; 425 return SPDK_SUCCESS; 426 } 427 } 428 429 /* copy the actual data into local buffer */ 430 if (pdu->data_valid_bytes < data_len) { 431 if (pdu->data_buf == NULL) { 432 if (data_len <= spdk_get_immediate_data_buffer_size()) { 433 pool = g_spdk_iscsi.pdu_immediate_data_pool; 434 } else if (data_len <= spdk_get_data_out_buffer_size()) { 435 pool = g_spdk_iscsi.pdu_data_out_pool; 436 } else { 437 SPDK_ERRLOG("Data(%d) > MaxSegment(%d)\n", 438 data_len, spdk_get_data_out_buffer_size()); 439 *_pdu = NULL; 440 spdk_put_pdu(pdu); 441 conn->pdu_in_progress = NULL; 442 return SPDK_ISCSI_CONNECTION_FATAL; 443 } 444 rte_mempool_get(pool, (void **)&pdu->mobj); 445 if (pdu->mobj == NULL) { 446 *_pdu = NULL; 447 return SPDK_SUCCESS; 448 } 449 pdu->data_buf = pdu->mobj->buf; 450 } 451 452 rc = spdk_iscsi_conn_read_data(conn, 453 data_len - pdu->data_valid_bytes, 454 pdu->data_buf + pdu->data_valid_bytes); 455 if (rc < 0) { 456 *_pdu = NULL; 457 spdk_put_pdu(pdu); 458 conn->pdu_in_progress = NULL; 459 return rc; 460 } 461 462 pdu->data_valid_bytes += rc; 463 if (pdu->data_valid_bytes < data_len) { 464 *_pdu = NULL; 465 return SPDK_SUCCESS; 466 } 467 } 468 469 /* copy out the data digest */ 470 if (conn->data_digest && data_len != 0 && 471 pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) { 472 rc = spdk_iscsi_conn_read_data(conn, 473 ISCSI_DIGEST_LEN - pdu->ddigest_valid_bytes, 474 pdu->data_digest + pdu->ddigest_valid_bytes); 475 if (rc < 0) { 476 *_pdu = NULL; 477 spdk_put_pdu(pdu); 478 conn->pdu_in_progress = NULL; 479 return rc; 480 } 481 482 pdu->ddigest_valid_bytes += rc; 483 if (pdu->ddigest_valid_bytes < ISCSI_DIGEST_LEN) { 484 *_pdu = NULL; 485 return SPDK_SUCCESS; 486 } 487 } 488 489 /* All data for this PDU has now been read from the socket. */ 490 conn->pdu_in_progress = NULL; 491 492 spdk_trace_record(TRACE_READ_PDU, conn->id, pdu->data_valid_bytes, 493 (uintptr_t)pdu, pdu->bhs.opcode); 494 495 /* Data Segment */ 496 if (data_len != 0) { 497 /* 498 * Determine the maximum segment length expected for this PDU. 499 * This will be used to make sure the initiator did not send 500 * us too much immediate data. 501 * 502 * This value is specified separately by the initiator and target, 503 * and not negotiated. So we can use the #define safely here, 504 * since the value is not dependent on the initiator's maximum 505 * segment lengths (FirstBurstLength/MaxRecvDataSegmentLength), 506 * and SPDK currently does not allow configuration of these values 507 * at runtime. 508 */ 509 if (conn->sess == NULL) { 510 /* 511 * If the connection does not yet have a session, then 512 * login is not complete and we use the 8KB default 513 * FirstBurstLength as our maximum data segment length 514 * value. 515 */ 516 max_segment_len = DEFAULT_FIRSTBURSTLENGTH; 517 } else if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAOUT) { 518 max_segment_len = spdk_get_data_out_buffer_size(); 519 } else if (pdu->bhs.opcode == ISCSI_OP_NOPOUT) { 520 max_segment_len = g_spdk_iscsi.MaxRecvDataSegmentLength; 521 } else { 522 max_segment_len = spdk_get_immediate_data_buffer_size(); 523 } 524 if (data_len > max_segment_len) { 525 SPDK_ERRLOG("Data(%d) > MaxSegment(%d)\n", 526 data_len, max_segment_len); 527 spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 528 spdk_put_pdu(pdu); 529 /* 530 * This PDU was rejected and will not be returned to 531 * the caller for execution. We do not want to 532 * drop the connection, so return SUCCESS here so that 533 * the caller will continue to attempt reading PDUs. 534 */ 535 return SPDK_SUCCESS; 536 } 537 538 pdu->data = pdu->data_buf; 539 pdu->data_from_mempool = true; 540 pdu->data_segment_len = data_len; 541 } 542 543 /* check digest */ 544 if (conn->header_digest) { 545 crc32c = spdk_iscsi_pdu_calc_header_digest(pdu); 546 rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c); 547 if (rc == 0) { 548 SPDK_ERRLOG("header digest error (%s)\n", conn->initiator_name); 549 spdk_put_pdu(pdu); 550 return SPDK_ISCSI_CONNECTION_FATAL; 551 } 552 } 553 if (conn->data_digest && data_len != 0) { 554 crc32c = spdk_iscsi_pdu_calc_data_digest(pdu); 555 rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c); 556 if (rc == 0) { 557 SPDK_ERRLOG("data digest error (%s)\n", conn->initiator_name); 558 spdk_put_pdu(pdu); 559 return SPDK_ISCSI_CONNECTION_FATAL; 560 } 561 } 562 563 *_pdu = pdu; 564 return 1; 565 } 566 567 int 568 spdk_iscsi_build_iovecs(struct spdk_iscsi_conn *conn, struct iovec *iovec, 569 struct spdk_iscsi_pdu *pdu) 570 { 571 int iovec_cnt = 0; 572 uint32_t crc32c; 573 int enable_digest; 574 int total_ahs_len; 575 int data_len; 576 577 total_ahs_len = pdu->bhs.total_ahs_len; 578 data_len = DGET24(pdu->bhs.data_segment_len); 579 580 enable_digest = 1; 581 if (pdu->bhs.opcode == ISCSI_OP_LOGIN_RSP) { 582 /* this PDU should be sent without digest */ 583 enable_digest = 0; 584 } 585 586 /* BHS */ 587 iovec[iovec_cnt].iov_base = &pdu->bhs; 588 iovec[iovec_cnt].iov_len = ISCSI_BHS_LEN; 589 iovec_cnt++; 590 591 /* AHS */ 592 if (total_ahs_len > 0) { 593 iovec[iovec_cnt].iov_base = pdu->ahs; 594 iovec[iovec_cnt].iov_len = 4 * total_ahs_len; 595 iovec_cnt++; 596 } 597 598 /* Header Digest */ 599 if (enable_digest && conn->header_digest) { 600 crc32c = spdk_iscsi_pdu_calc_header_digest(pdu); 601 MAKE_DIGEST_WORD(pdu->header_digest, crc32c); 602 603 iovec[iovec_cnt].iov_base = pdu->header_digest; 604 iovec[iovec_cnt].iov_len = ISCSI_DIGEST_LEN; 605 iovec_cnt++; 606 } 607 608 /* Data Segment */ 609 if (data_len > 0) { 610 iovec[iovec_cnt].iov_base = pdu->data; 611 iovec[iovec_cnt].iov_len = ISCSI_ALIGN(data_len); 612 iovec_cnt++; 613 } 614 615 /* Data Digest */ 616 if (enable_digest && conn->data_digest && data_len != 0) { 617 crc32c = spdk_iscsi_pdu_calc_data_digest(pdu); 618 MAKE_DIGEST_WORD(pdu->data_digest, crc32c); 619 620 iovec[iovec_cnt].iov_base = pdu->data_digest; 621 iovec[iovec_cnt].iov_len = ISCSI_DIGEST_LEN; 622 iovec_cnt++; 623 } 624 625 return iovec_cnt; 626 } 627 628 static void 629 spdk_iscsi_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 630 { 631 TAILQ_INSERT_TAIL(&conn->write_pdu_list, pdu, tailq); 632 } 633 634 static int 635 spdk_iscsi_append_text(struct spdk_iscsi_conn *conn __attribute__(( 636 __unused__)), const char *key, const char *val, uint8_t *data, int alloc_len, 637 int data_len) 638 { 639 int total; 640 int len; 641 642 total = data_len; 643 if (alloc_len < 1) { 644 return 0; 645 } 646 if (total > alloc_len) { 647 total = alloc_len; 648 data[total - 1] = '\0'; 649 return total; 650 } 651 652 if (alloc_len - total < 1) { 653 SPDK_ERRLOG("data space small %d\n", alloc_len); 654 return total; 655 } 656 len = snprintf((char *) data + total, alloc_len - total, "%s=%s", 657 key, val); 658 total += len + 1; 659 660 return total; 661 } 662 663 static int 664 spdk_iscsi_append_param(struct spdk_iscsi_conn *conn, const char *key, 665 uint8_t *data, int alloc_len, int data_len) 666 { 667 struct iscsi_param *param; 668 int rc; 669 670 param = spdk_iscsi_param_find(conn->params, key); 671 if (param == NULL) { 672 param = spdk_iscsi_param_find(conn->sess->params, key); 673 if (param == NULL) { 674 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "no key %.64s\n", 675 key); 676 return data_len; 677 } 678 } 679 rc = spdk_iscsi_append_text(conn, param->key, param->val, data, 680 alloc_len, data_len); 681 return rc; 682 } 683 684 static int 685 spdk_iscsi_chap_get_authinfo(struct iscsi_chap_auth *auth, const char *authfile, 686 const char *authuser, int ag_tag) 687 { 688 struct spdk_conf *config = NULL; 689 struct spdk_conf_section *sp; 690 const char *val; 691 const char *user, *muser; 692 const char *secret, *msecret; 693 int rc; 694 int i; 695 696 if (auth->user != NULL) { 697 free(auth->user); 698 free(auth->secret); 699 free(auth->muser); 700 free(auth->msecret); 701 auth->user = auth->secret = NULL; 702 auth->muser = auth->msecret = NULL; 703 } 704 705 /* read config files */ 706 config = spdk_conf_allocate(); 707 if (config == NULL) { 708 SPDK_ERRLOG("allocate config fail\n"); 709 return -1; 710 } 711 rc = spdk_conf_read(config, authfile); 712 if (rc < 0) { 713 SPDK_ERRLOG("auth conf error\n"); 714 spdk_conf_free(config); 715 return -1; 716 } 717 //spdk_conf_print(config); 718 719 sp = spdk_conf_first_section(config); 720 while (sp != NULL) { 721 if (spdk_conf_section_match_prefix(sp, "AuthGroup")) { 722 int group = spdk_conf_section_get_num(sp); 723 724 if (group == 0) { 725 SPDK_ERRLOG("Group 0 is invalid\n"); 726 spdk_conf_free(config); 727 return -1; 728 } 729 if (ag_tag != group) { 730 goto skip_ag_tag; 731 } 732 733 val = spdk_conf_section_get_val(sp, "Comment"); 734 if (val != NULL) { 735 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 736 "Comment %s\n", val); 737 } 738 for (i = 0; ; i++) { 739 val = spdk_conf_section_get_nval(sp, "Auth", i); 740 if (val == NULL) 741 break; 742 user = spdk_conf_section_get_nmval(sp, "Auth", i, 0); 743 secret = spdk_conf_section_get_nmval(sp, "Auth", i, 1); 744 muser = spdk_conf_section_get_nmval(sp, "Auth", i, 2); 745 msecret = spdk_conf_section_get_nmval(sp, "Auth", i, 3); 746 if (user != NULL) { 747 if (strcasecmp(authuser, user) == 0) { 748 /* match user */ 749 auth->user = xstrdup(user); 750 auth->secret = xstrdup(secret); 751 auth->muser = xstrdup(muser); 752 auth->msecret = xstrdup(msecret); 753 spdk_conf_free(config); 754 return 0; 755 } 756 } else { 757 SPDK_ERRLOG("Invalid Auth format, skip this line\n"); 758 continue; 759 } 760 } 761 } 762 skip_ag_tag: 763 sp = spdk_conf_next_section(sp); 764 } 765 766 spdk_conf_free(config); 767 return 0; 768 } 769 770 static int 771 spdk_iscsi_get_authinfo(struct spdk_iscsi_conn *conn, const char *authuser) 772 { 773 char *authfile = NULL; 774 int ag_tag; 775 int rc; 776 777 if (conn->sess->target != NULL) { 778 ag_tag = conn->sess->target->auth_group; 779 } else { 780 ag_tag = -1; 781 } 782 if (ag_tag < 0) { 783 pthread_mutex_lock(&g_spdk_iscsi.mutex); 784 ag_tag = g_spdk_iscsi.discovery_auth_group; 785 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 786 } 787 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "ag_tag=%d\n", ag_tag); 788 789 pthread_mutex_lock(&g_spdk_iscsi.mutex); 790 authfile = strdup(g_spdk_iscsi.authfile); 791 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 792 if (!authfile) { 793 perror("authfile"); 794 return -ENOMEM; 795 } 796 797 rc = spdk_iscsi_chap_get_authinfo(&conn->auth, authfile, authuser, ag_tag); 798 if (rc < 0) { 799 SPDK_ERRLOG("chap_get_authinfo() failed\n"); 800 free(authfile); 801 return -1; 802 } 803 free(authfile); 804 return 0; 805 } 806 807 static int 808 spdk_iscsi_auth_params(struct spdk_iscsi_conn *conn, 809 struct iscsi_param *params, const char *method, uint8_t *data, int alloc_len, 810 int data_len) 811 { 812 char *in_val; 813 char *in_next; 814 char *new_val; 815 const char *val; 816 const char *user; 817 const char *response; 818 const char *challenge; 819 int total; 820 int rc; 821 822 if (conn == NULL || params == NULL || method == NULL) { 823 return -1; 824 } 825 if (strcasecmp(method, "CHAP") == 0) { 826 /* method OK */ 827 } else { 828 SPDK_ERRLOG("unsupported AuthMethod %.64s\n", method); 829 return -1; 830 } 831 832 total = data_len; 833 if (alloc_len < 1) { 834 return 0; 835 } 836 if (total > alloc_len) { 837 total = alloc_len; 838 data[total - 1] = '\0'; 839 return total; 840 } 841 842 /* for temporary store */ 843 in_val = malloc(ISCSI_TEXT_MAX_VAL_LEN + 1); 844 if (!in_val) { 845 perror("in_val"); 846 return -ENOMEM; 847 } 848 849 /* CHAP method (RFC1994) */ 850 if ((val = spdk_iscsi_param_get_val(params, "CHAP_A")) != NULL) { 851 if (conn->auth.chap_phase != ISCSI_CHAP_PHASE_WAIT_A) { 852 SPDK_ERRLOG("CHAP sequence error\n"); 853 goto error_return; 854 } 855 856 /* CHAP_A is LIST type */ 857 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", val); 858 in_next = in_val; 859 while ((new_val = spdk_strsepq(&in_next, ",")) != NULL) { 860 if (strcasecmp(new_val, "5") == 0) { 861 /* CHAP with MD5 */ 862 break; 863 } 864 } 865 if (new_val == NULL) { 866 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN + 1, "%s", "Reject"); 867 new_val = in_val; 868 spdk_iscsi_append_text(conn, "CHAP_A", new_val, 869 data, alloc_len, total); 870 goto error_return; 871 } 872 /* selected algorithm is 5 (MD5) */ 873 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "got CHAP_A=%s\n", new_val); 874 total = spdk_iscsi_append_text(conn, "CHAP_A", new_val, 875 data, alloc_len, total); 876 877 /* Identifier is one octet */ 878 spdk_gen_random(conn->auth.chap_id, 1); 879 snprintf(in_val, ISCSI_TEXT_MAX_VAL_LEN, "%d", 880 (int) conn->auth.chap_id[0]); 881 total = spdk_iscsi_append_text(conn, "CHAP_I", in_val, 882 data, alloc_len, total); 883 884 /* Challenge Value is a variable stream of octets */ 885 /* (binary length MUST not exceed 1024 bytes) */ 886 conn->auth.chap_challenge_len = ISCSI_CHAP_CHALLENGE_LEN; 887 spdk_gen_random(conn->auth.chap_challenge, 888 conn->auth.chap_challenge_len); 889 spdk_bin2hex(in_val, ISCSI_TEXT_MAX_VAL_LEN, 890 conn->auth.chap_challenge, 891 conn->auth.chap_challenge_len); 892 total = spdk_iscsi_append_text(conn, "CHAP_C", in_val, 893 data, alloc_len, total); 894 895 conn->auth.chap_phase = ISCSI_CHAP_PHASE_WAIT_NR; 896 } else if ((val = spdk_iscsi_param_get_val(params, "CHAP_N")) != NULL) { 897 uint8_t resmd5[SPDK_MD5DIGEST_LEN]; 898 uint8_t tgtmd5[SPDK_MD5DIGEST_LEN]; 899 struct spdk_md5ctx md5ctx; 900 901 user = val; 902 if (conn->auth.chap_phase != ISCSI_CHAP_PHASE_WAIT_NR) { 903 SPDK_ERRLOG("CHAP sequence error\n"); 904 goto error_return; 905 } 906 907 response = spdk_iscsi_param_get_val(params, "CHAP_R"); 908 if (response == NULL) { 909 SPDK_ERRLOG("no response\n"); 910 goto error_return; 911 } 912 rc = spdk_hex2bin(resmd5, SPDK_MD5DIGEST_LEN, response); 913 if (rc < 0 || rc != SPDK_MD5DIGEST_LEN) { 914 SPDK_ERRLOG("response format error\n"); 915 goto error_return; 916 } 917 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "got CHAP_N/CHAP_R\n"); 918 919 rc = spdk_iscsi_get_authinfo(conn, val); 920 if (rc < 0) { 921 //SPDK_ERRLOG("auth user or secret is missing\n"); 922 SPDK_ERRLOG("iscsi_get_authinfo() failed\n"); 923 goto error_return; 924 } 925 if (conn->auth.user == NULL || conn->auth.secret == NULL) { 926 //SPDK_ERRLOG("auth user or secret is missing\n"); 927 SPDK_ERRLOG("auth failed (user %.64s)\n", user); 928 goto error_return; 929 } 930 931 spdk_md5init(&md5ctx); 932 /* Identifier */ 933 spdk_md5update(&md5ctx, conn->auth.chap_id, 1); 934 /* followed by secret */ 935 spdk_md5update(&md5ctx, conn->auth.secret, 936 strlen(conn->auth.secret)); 937 /* followed by Challenge Value */ 938 spdk_md5update(&md5ctx, conn->auth.chap_challenge, 939 conn->auth.chap_challenge_len); 940 /* tgtmd5 is expecting Response Value */ 941 spdk_md5final(tgtmd5, &md5ctx); 942 943 spdk_bin2hex(in_val, ISCSI_TEXT_MAX_VAL_LEN, 944 tgtmd5, SPDK_MD5DIGEST_LEN); 945 946 #if 0 947 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "tgtmd5=%s, resmd5=%s\n", in_val, response); 948 spdk_dump("tgtmd5", tgtmd5, SPDK_MD5DIGEST_LEN); 949 spdk_dump("resmd5", resmd5, SPDK_MD5DIGEST_LEN); 950 #endif 951 952 /* compare MD5 digest */ 953 if (memcmp(tgtmd5, resmd5, SPDK_MD5DIGEST_LEN) != 0) { 954 /* not match */ 955 //SPDK_ERRLOG("auth user or secret is missing\n"); 956 SPDK_ERRLOG("auth failed (user %.64s)\n", user); 957 goto error_return; 958 } 959 /* OK initiator's secret */ 960 conn->authenticated = 1; 961 962 /* mutual CHAP? */ 963 val = spdk_iscsi_param_get_val(params, "CHAP_I"); 964 if (val != NULL) { 965 conn->auth.chap_mid[0] = (uint8_t) strtol(val, NULL, 10); 966 challenge = spdk_iscsi_param_get_val(params, "CHAP_C"); 967 if (challenge == NULL) { 968 SPDK_ERRLOG("CHAP sequence error\n"); 969 goto error_return; 970 } 971 rc = spdk_hex2bin(conn->auth.chap_mchallenge, 972 ISCSI_CHAP_CHALLENGE_LEN, 973 challenge); 974 if (rc < 0) { 975 SPDK_ERRLOG("challenge format error\n"); 976 goto error_return; 977 } 978 conn->auth.chap_mchallenge_len = rc; 979 #if 0 980 spdk_dump("MChallenge", conn->auth.chap_mchallenge, 981 conn->auth.chap_mchallenge_len); 982 #endif 983 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 984 "got CHAP_I/CHAP_C\n"); 985 986 if (conn->auth.muser == NULL || conn->auth.msecret == NULL) { 987 //SPDK_ERRLOG("mutual auth user or secret is missing\n"); 988 SPDK_ERRLOG("auth failed (user %.64s)\n", user); 989 goto error_return; 990 } 991 992 spdk_md5init(&md5ctx); 993 /* Identifier */ 994 spdk_md5update(&md5ctx, conn->auth.chap_mid, 1); 995 /* followed by secret */ 996 spdk_md5update(&md5ctx, conn->auth.msecret, 997 strlen(conn->auth.msecret)); 998 /* followed by Challenge Value */ 999 spdk_md5update(&md5ctx, conn->auth.chap_mchallenge, 1000 conn->auth.chap_mchallenge_len); 1001 /* tgtmd5 is Response Value */ 1002 spdk_md5final(tgtmd5, &md5ctx); 1003 1004 spdk_bin2hex(in_val, ISCSI_TEXT_MAX_VAL_LEN, 1005 tgtmd5, SPDK_MD5DIGEST_LEN); 1006 1007 total = spdk_iscsi_append_text(conn, "CHAP_N", 1008 conn->auth.muser, data, alloc_len, total); 1009 total = spdk_iscsi_append_text(conn, "CHAP_R", 1010 in_val, data, alloc_len, total); 1011 } else { 1012 /* not mutual */ 1013 if (conn->req_mutual) { 1014 SPDK_ERRLOG("required mutual CHAP\n"); 1015 goto error_return; 1016 } 1017 } 1018 1019 conn->auth.chap_phase = ISCSI_CHAP_PHASE_END; 1020 } else { 1021 /* not found CHAP keys */ 1022 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "start CHAP\n"); 1023 conn->auth.chap_phase = ISCSI_CHAP_PHASE_WAIT_A; 1024 } 1025 1026 free(in_val); 1027 return total; 1028 1029 error_return: 1030 conn->auth.chap_phase = ISCSI_CHAP_PHASE_WAIT_A; 1031 free(in_val); 1032 return -1; 1033 } 1034 1035 static int 1036 spdk_iscsi_reject(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu, 1037 int reason) 1038 { 1039 struct spdk_iscsi_pdu *rsp_pdu; 1040 struct iscsi_bhs_reject *rsph; 1041 uint8_t *data; 1042 int total_ahs_len; 1043 int data_len; 1044 int alloc_len; 1045 1046 total_ahs_len = pdu->bhs.total_ahs_len; 1047 data_len = 0; 1048 alloc_len = ISCSI_BHS_LEN + (4 * total_ahs_len); 1049 1050 if (conn->header_digest) 1051 alloc_len += ISCSI_DIGEST_LEN; 1052 1053 data = malloc(alloc_len); 1054 if (!data) { 1055 perror("data"); 1056 return -ENOMEM; 1057 } 1058 1059 memset(data, 0, alloc_len); 1060 1061 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Reject PDU reason=%d\n", reason); 1062 1063 if (conn->sess != NULL) { 1064 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 1065 "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n", 1066 conn->StatSN, conn->sess->ExpCmdSN, 1067 conn->sess->MaxCmdSN); 1068 } else { 1069 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "StatSN=%u\n", conn->StatSN); 1070 } 1071 1072 memcpy(data, &pdu->bhs, ISCSI_BHS_LEN); 1073 data_len += ISCSI_BHS_LEN; 1074 1075 if (total_ahs_len != 0) { 1076 memcpy(data + data_len, pdu->ahs, (4 * total_ahs_len)); 1077 data_len += (4 * total_ahs_len); 1078 } 1079 1080 if (conn->header_digest) { 1081 memcpy(data + data_len, pdu->header_digest, ISCSI_DIGEST_LEN); 1082 data_len += ISCSI_DIGEST_LEN; 1083 } 1084 1085 rsp_pdu = spdk_get_pdu(); 1086 rsph = (struct iscsi_bhs_reject *)&rsp_pdu->bhs; 1087 rsp_pdu->data = data; 1088 rsph->opcode = ISCSI_OP_REJECT; 1089 rsph->flags |= 0x80; /* bit 0 is default to 1 */ 1090 rsph->reason = reason; 1091 DSET24(rsph->data_segment_len, data_len); 1092 1093 rsph->ffffffff = 0xffffffffU; 1094 to_be32(&rsph->stat_sn, conn->StatSN); 1095 conn->StatSN++; 1096 1097 if (conn->sess != NULL) { 1098 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 1099 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 1100 } else { 1101 to_be32(&rsph->exp_cmd_sn, 1); 1102 to_be32(&rsph->max_cmd_sn, 1); 1103 } 1104 1105 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "PDU", (void *)&rsp_pdu->bhs, ISCSI_BHS_LEN); 1106 1107 spdk_iscsi_write_pdu(conn, rsp_pdu); 1108 1109 return 0; 1110 } 1111 1112 static int 1113 spdk_iscsi_check_values(struct spdk_iscsi_conn *conn) 1114 { 1115 if (conn->sess->FirstBurstLength > conn->sess->MaxBurstLength) { 1116 SPDK_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n", 1117 conn->sess->FirstBurstLength, 1118 conn->sess->MaxBurstLength); 1119 return -1; 1120 } 1121 if (conn->sess->FirstBurstLength > g_spdk_iscsi.FirstBurstLength) { 1122 SPDK_ERRLOG("FirstBurstLength(%d) > iSCSI target restriction(%d)\n", 1123 conn->sess->FirstBurstLength, 1124 g_spdk_iscsi.FirstBurstLength); 1125 return -1; 1126 } 1127 if (conn->sess->MaxBurstLength > 0x00ffffff) { 1128 SPDK_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n", 1129 conn->sess->MaxBurstLength); 1130 return -1; 1131 } 1132 1133 if (conn->MaxRecvDataSegmentLength < 512) { 1134 SPDK_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n", 1135 conn->MaxRecvDataSegmentLength); 1136 return -1; 1137 } 1138 if (conn->MaxRecvDataSegmentLength > 0x00ffffff) { 1139 SPDK_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n", 1140 conn->MaxRecvDataSegmentLength); 1141 return -1; 1142 } 1143 return 0; 1144 } 1145 1146 1147 /* 1148 * The response function of spdk_iscsi_op_login 1149 * return: 1150 * 0:success; 1151 * -1:error; 1152 */ 1153 static int 1154 spdk_iscsi_op_login_response(struct spdk_iscsi_conn *conn, 1155 struct spdk_iscsi_pdu *rsp_pdu, struct iscsi_param *params) 1156 { 1157 struct iscsi_bhs_login_rsp *rsph; 1158 int rc; 1159 1160 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1161 rsph->version_max = ISCSI_VERSION; 1162 rsph->version_act = ISCSI_VERSION; 1163 DSET24(rsph->data_segment_len, rsp_pdu->data_segment_len); 1164 1165 to_be32(&rsph->stat_sn, conn->StatSN); 1166 conn->StatSN++; 1167 1168 if (conn->sess != NULL) { 1169 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 1170 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 1171 } else { 1172 to_be32(&rsph->exp_cmd_sn, rsp_pdu->cmd_sn); 1173 to_be32(&rsph->max_cmd_sn, rsp_pdu->cmd_sn); 1174 } 1175 1176 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "PDU", (uint8_t *)rsph, ISCSI_BHS_LEN); 1177 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "DATA", rsp_pdu->data, rsp_pdu->data_segment_len); 1178 1179 /* Set T/CSG/NSG to reserved if login error. */ 1180 if (rsph->status_class != 0) { 1181 rsph->flags &= ~ISCSI_LOGIN_TRANSIT; 1182 rsph->flags &= ~ISCSI_LOGIN_CURRENT_STAGE_MASK; 1183 rsph->flags &= ~ISCSI_LOGIN_NEXT_STAGE_MASK; 1184 } 1185 spdk_iscsi_write_pdu(conn, rsp_pdu); 1186 1187 /* after send PDU digest on/off */ 1188 if (conn->full_feature) { 1189 /* update internal variables */ 1190 rc = spdk_iscsi_copy_param2var(conn); 1191 if (rc < 0) { 1192 SPDK_ERRLOG("spdk_iscsi_copy_param2var() failed\n"); 1193 spdk_iscsi_param_free(params); 1194 return -1; 1195 } 1196 /* check value */ 1197 rc = spdk_iscsi_check_values(conn); 1198 if (rc < 0) { 1199 SPDK_ERRLOG("iscsi_check_values() failed\n"); 1200 spdk_iscsi_param_free(params); 1201 return -1; 1202 } 1203 } 1204 1205 spdk_iscsi_param_free(params); 1206 return 0; 1207 1208 } 1209 1210 /* 1211 * This function is used to del the original param and update it with new 1212 * value 1213 * return: 1214 * 0: success 1215 * otherwise: error 1216 */ 1217 static int 1218 spdk_iscsi_op_login_update_param(struct spdk_iscsi_conn *conn, 1219 const char *key, const char *value, 1220 const char *list) 1221 { 1222 int rc = 0; 1223 struct iscsi_param *new_param, *orig_param; 1224 int index; 1225 1226 orig_param = spdk_iscsi_param_find(conn->params, key); 1227 if (orig_param == NULL) { 1228 SPDK_ERRLOG("orig_param %s not found\n", key); 1229 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1230 } 1231 1232 index = orig_param->state_index; 1233 rc = spdk_iscsi_param_del(&conn->params, key); 1234 if (rc < 0) { 1235 SPDK_ERRLOG("iscsi_param_del(%s) failed\n", key); 1236 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1237 } 1238 rc = spdk_iscsi_param_add(&conn->params, key, value, list, ISPT_LIST); 1239 if (rc < 0) { 1240 SPDK_ERRLOG("iscsi_param_add() failed\n"); 1241 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1242 } 1243 new_param = spdk_iscsi_param_find(conn->params, key); 1244 if (new_param == NULL) { 1245 SPDK_ERRLOG("spdk_iscsi_param_find() failed\n"); 1246 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1247 } 1248 new_param->state_index = index; 1249 return rc; 1250 } 1251 1252 /* 1253 * The function which is used to handle the part of session discovery 1254 * return: 1255 * 0, success; 1256 * otherwise: error; 1257 */ 1258 static int 1259 spdk_iscsi_op_login_session_discovery_chap(struct spdk_iscsi_conn *conn) 1260 { 1261 int rc = 0; 1262 1263 if (g_spdk_iscsi.no_discovery_auth) { 1264 conn->req_auth = 0; 1265 rc = spdk_iscsi_op_login_update_param(conn, "AuthMethod", 1266 "None", "None"); 1267 if (rc < 0) 1268 return rc; 1269 } else if (g_spdk_iscsi.req_discovery_auth) { 1270 conn->req_auth = 1; 1271 rc = spdk_iscsi_op_login_update_param(conn, "AuthMethod", 1272 "CHAP", "CHAP"); 1273 if (rc < 0) 1274 return rc; 1275 } 1276 if (g_spdk_iscsi.req_discovery_auth_mutual) 1277 conn->req_mutual = 1; 1278 1279 return rc; 1280 1281 } 1282 1283 /* 1284 * This function is used to update the param related with chap 1285 * return: 1286 * 0: success 1287 * otherwise: error 1288 */ 1289 static int 1290 spdk_iscsi_op_login_negotiate_chap_param(struct spdk_iscsi_conn *conn, 1291 struct spdk_iscsi_pdu *rsp_pdu, 1292 struct spdk_iscsi_tgt_node *target) 1293 { 1294 int rc; 1295 1296 if (target->auth_chap_disabled) { 1297 conn->req_auth = 0; 1298 rc = spdk_iscsi_op_login_update_param(conn, "AuthMethod", 1299 "None", "None"); 1300 if (rc < 0) 1301 return rc; 1302 } else if (target->auth_chap_required) { 1303 conn->req_auth = 1; 1304 rc = spdk_iscsi_op_login_update_param(conn, "AuthMethod", 1305 "CHAP", "CHAP"); 1306 if (rc < 0) 1307 return rc; 1308 } 1309 1310 if (target->auth_chap_mutual) 1311 conn->req_mutual = 1; 1312 1313 if (target->header_digest) { 1314 /* 1315 * User specified header digests, so update the list of 1316 * HeaderDigest values to remove "None" so that only 1317 * initiators who support CRC32C can connect. 1318 */ 1319 rc = spdk_iscsi_op_login_update_param(conn, "HeaderDigest", 1320 "CRC32C", "CRC32C"); 1321 if (rc < 0) 1322 return rc; 1323 } 1324 1325 if (target->data_digest) { 1326 /* 1327 * User specified data digests, so update the list of 1328 * DataDigest values to remove "None" so that only 1329 * initiators who support CRC32C can connect. 1330 */ 1331 rc = spdk_iscsi_op_login_update_param(conn, "DataDigest", 1332 "CRC32C", "CRC32C"); 1333 if (rc < 0) 1334 return rc; 1335 } 1336 1337 return 0; 1338 } 1339 1340 /* 1341 * This function use to check the session 1342 * return: 1343 * 0, success 1344 * otherwise: error 1345 */ 1346 static int 1347 spdk_iscsi_op_login_check_session(struct spdk_iscsi_conn *conn, 1348 struct spdk_iscsi_pdu *rsp_pdu, 1349 char *initiator_port_name, int cid) 1350 1351 { 1352 int rc = 0; 1353 struct iscsi_bhs_login_rsp *rsph; 1354 1355 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1356 /* check existing session */ 1357 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "isid=%"PRIx64", tsih=%u, cid=%u\n", 1358 spdk_iscsi_get_isid(rsph->isid), from_be16(&rsph->tsih), cid); 1359 if (rsph->tsih != 0) { 1360 /* multiple connections */ 1361 rc = spdk_append_iscsi_sess(conn, initiator_port_name, 1362 from_be16(&rsph->tsih), cid); 1363 if (rc < 0) { 1364 SPDK_ERRLOG("isid=%"PRIx64", tsih=%u, cid=%u:" 1365 "spdk_append_iscsi_sess() failed\n", 1366 spdk_iscsi_get_isid(rsph->isid), from_be16(&rsph->tsih), 1367 cid); 1368 /* Can't include in session */ 1369 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1370 rsph->status_detail = ISCSI_LOGIN_CONN_ADD_FAIL; 1371 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1372 } 1373 } else if (!g_spdk_iscsi.AllowDuplicateIsid) { 1374 /* new session, drop old sess by the initiator */ 1375 spdk_iscsi_drop_conns(conn, initiator_port_name, 1376 0 /* drop old */); 1377 } 1378 1379 return rc; 1380 } 1381 1382 /* 1383 * This function is used to check the target info 1384 * return: 1385 * 0: success 1386 * otherwise: error 1387 */ 1388 static int 1389 spdk_iscsi_op_login_check_target(struct spdk_iscsi_conn *conn, 1390 struct spdk_iscsi_pdu *rsp_pdu, 1391 const char *target_name, 1392 struct spdk_iscsi_tgt_node **target) 1393 1394 { 1395 int rc; 1396 struct iscsi_bhs_login_rsp *rsph; 1397 1398 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1399 *target = spdk_iscsi_find_tgt_node(target_name); 1400 if (*target == NULL) { 1401 SPDK_WARNLOG("target %s not found\n", target_name); 1402 /* Not found */ 1403 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1404 rsph->status_detail = ISCSI_LOGIN_TARGET_NOT_FOUND; 1405 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1406 } 1407 rc = spdk_iscsi_tgt_node_access(conn, *target, 1408 conn->initiator_name, 1409 conn->initiator_addr); 1410 if (rc < 0) { 1411 SPDK_WARNLOG("lu_access() failed\n"); 1412 /* Not found */ 1413 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1414 rsph->status_detail = ISCSI_LOGIN_TARGET_NOT_FOUND; 1415 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1416 } 1417 if (rc == 0) { 1418 SPDK_ERRLOG("access denied\n"); 1419 /* Not found */ 1420 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1421 rsph->status_detail = ISCSI_LOGIN_TARGET_NOT_FOUND; 1422 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1423 } 1424 1425 return 0; 1426 } 1427 1428 /* 1429 * The function which is used to handle the part of normal login session 1430 * return: 1431 * 0, success; 1432 * SPDK_ISCSI_LOGIN_ERROR_PARAMETER, parameter error; 1433 */ 1434 static int 1435 spdk_iscsi_op_login_session_normal(struct spdk_iscsi_conn *conn, 1436 struct spdk_iscsi_pdu *rsp_pdu, 1437 char *initiator_port_name, 1438 struct iscsi_param *params, 1439 struct spdk_iscsi_tgt_node **target, 1440 int cid) 1441 { 1442 const char *target_name; 1443 const char *target_short_name; 1444 struct iscsi_bhs_login_rsp *rsph; 1445 int rc = 0; 1446 1447 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1448 target_name = spdk_iscsi_param_get_val(params, "TargetName"); 1449 1450 if (target_name == NULL) { 1451 SPDK_ERRLOG("TargetName is empty\n"); 1452 /* Missing parameter */ 1453 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1454 rsph->status_detail = ISCSI_LOGIN_MISSING_PARMS; 1455 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1456 } 1457 1458 memset(conn->target_short_name, 0, MAX_TARGET_NAME); 1459 target_short_name = strstr(target_name, ":"); 1460 if (target_short_name != NULL) { 1461 target_short_name++; /* Advance past the ':' */ 1462 if (strlen(target_short_name) >= MAX_TARGET_NAME) { 1463 SPDK_ERRLOG("Target Short Name (%s) is more than %u characters\n", 1464 target_short_name, MAX_TARGET_NAME); 1465 return rc; 1466 } 1467 snprintf(conn->target_short_name, MAX_TARGET_NAME, "%s", 1468 target_short_name); 1469 } 1470 1471 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1472 rc = spdk_iscsi_op_login_check_target(conn, rsp_pdu, target_name, 1473 target); 1474 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1475 1476 if (rc < 0) 1477 return rc; 1478 1479 conn->target = *target; 1480 conn->dev = (*target)->dev; 1481 conn->target_port = spdk_scsi_dev_find_port_by_id((*target)->dev, 1482 conn->portal->group->tag); 1483 1484 rc = spdk_iscsi_op_login_check_session(conn, rsp_pdu, 1485 initiator_port_name, cid); 1486 if (rc < 0) 1487 return rc; 1488 1489 /* force target flags */ 1490 pthread_mutex_lock(&((*target)->mutex)); 1491 rc = spdk_iscsi_op_login_negotiate_chap_param(conn, rsp_pdu, *target); 1492 pthread_mutex_unlock(&((*target)->mutex)); 1493 1494 return rc; 1495 } 1496 1497 /* 1498 * This function is used to judge the session type 1499 * return 1500 * 0: success 1501 * otherwise, error 1502 */ 1503 static int 1504 spdk_iscsi_op_login_session_type(struct spdk_iscsi_conn *conn, 1505 struct spdk_iscsi_pdu *rsp_pdu, 1506 enum session_type *session_type, 1507 struct iscsi_param *params) 1508 { 1509 const char *session_type_str; 1510 struct iscsi_bhs_login_rsp *rsph; 1511 1512 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1513 session_type_str = spdk_iscsi_param_get_val(params, "SessionType"); 1514 if (session_type_str == NULL) { 1515 if (rsph->tsih != 0) 1516 *session_type = SESSION_TYPE_NORMAL; 1517 else { 1518 SPDK_ERRLOG("SessionType is empty\n"); 1519 /* Missing parameter */ 1520 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1521 rsph->status_detail = ISCSI_LOGIN_MISSING_PARMS; 1522 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1523 } 1524 } else { 1525 if (strcasecmp(session_type_str, "Discovery") == 0) 1526 *session_type = SESSION_TYPE_DISCOVERY; 1527 else if (strcasecmp(session_type_str, "Normal") == 0) 1528 *session_type = SESSION_TYPE_NORMAL; 1529 else { 1530 *session_type = SESSION_TYPE_INVALID; 1531 SPDK_ERRLOG("SessionType is invalid\n"); 1532 /* Missing parameter */ 1533 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1534 rsph->status_detail = ISCSI_LOGIN_MISSING_PARMS; 1535 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1536 } 1537 } 1538 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Session Type: %s\n", session_type_str); 1539 1540 return 0; 1541 } 1542 /* 1543 * This function is used to initialize the port info 1544 * return 1545 * 0: success 1546 * otherwise: error 1547 */ 1548 static int 1549 spdk_iscsi_op_login_initialize_port(struct spdk_iscsi_conn *conn, 1550 struct spdk_iscsi_pdu *rsp_pdu, 1551 char *initiator_port_name, 1552 uint32_t name_length, 1553 struct iscsi_param *params) 1554 { 1555 const char *val; 1556 struct iscsi_bhs_login_rsp *rsph; 1557 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1558 1559 /* Initiator Name and Port */ 1560 val = spdk_iscsi_param_get_val(params, "InitiatorName"); 1561 if (val == NULL) { 1562 SPDK_ERRLOG("InitiatorName is empty\n"); 1563 /* Missing parameter */ 1564 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1565 rsph->status_detail = ISCSI_LOGIN_MISSING_PARMS; 1566 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1567 } 1568 snprintf(conn->initiator_name, sizeof(conn->initiator_name), 1569 "%s", val); 1570 snprintf(initiator_port_name, name_length, 1571 "%s,i,0x%12.12" PRIx64, val, spdk_iscsi_get_isid(rsph->isid)); 1572 spdk_strlwr(conn->initiator_name); 1573 spdk_strlwr(initiator_port_name); 1574 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Initiator name: %s\n", 1575 conn->initiator_name); 1576 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Initiator port: %s\n", 1577 initiator_port_name); 1578 1579 return 0; 1580 } 1581 1582 /* 1583 * This function is used to set the info in the connection data structure 1584 * return 1585 * 0: success 1586 * otherwise: error 1587 */ 1588 static int 1589 spdk_iscsi_op_login_set_conn_info(struct spdk_iscsi_conn *conn, 1590 struct spdk_iscsi_pdu *rsp_pdu, 1591 char *initiator_port_name, 1592 enum session_type session_type, 1593 struct spdk_iscsi_tgt_node *target, int cid) 1594 { 1595 int rc = 0; 1596 struct iscsi_bhs_login_rsp *rsph; 1597 1598 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1599 conn->authenticated = 0; 1600 conn->auth.chap_phase = ISCSI_CHAP_PHASE_WAIT_A; 1601 conn->cid = cid; 1602 1603 if (conn->sess == NULL) { 1604 /* new session */ 1605 rc = spdk_create_iscsi_sess(conn, target, session_type); 1606 if (rc < 0) { 1607 SPDK_ERRLOG("create_sess() failed\n"); 1608 rsph->status_class = ISCSI_CLASS_TARGET_ERROR; 1609 rsph->status_detail = ISCSI_LOGIN_STATUS_NO_RESOURCES; 1610 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1611 } 1612 1613 /* initialize parameters */ 1614 conn->StatSN = from_be32(&rsph->stat_sn); 1615 conn->sess->initiator_port = spdk_scsi_port_create(spdk_iscsi_get_isid(rsph->isid), 0, 1616 initiator_port_name); 1617 conn->sess->isid = spdk_iscsi_get_isid(rsph->isid); 1618 conn->sess->target = target; 1619 1620 /* Discovery sessions will not have a target. */ 1621 if (target != NULL) { 1622 conn->sess->queue_depth = target->queue_depth; 1623 } else { 1624 /* 1625 * Assume discovery sessions have an effective command 1626 * windows size of 1. 1627 */ 1628 conn->sess->queue_depth = 1; 1629 } 1630 conn->sess->ExpCmdSN = rsp_pdu->cmd_sn; 1631 conn->sess->MaxCmdSN = rsp_pdu->cmd_sn + conn->sess->queue_depth - 1; 1632 } 1633 1634 conn->initiator_port = conn->sess->initiator_port; 1635 1636 return 0; 1637 } 1638 1639 /* 1640 * This function is used to set the target info 1641 * return 1642 * 0: success 1643 * otherwise: error 1644 */ 1645 static int 1646 spdk_iscsi_op_login_set_target_info(struct spdk_iscsi_conn *conn, 1647 struct spdk_iscsi_pdu *rsp_pdu, 1648 enum session_type session_type, 1649 int alloc_len, 1650 struct spdk_iscsi_tgt_node *target) 1651 { 1652 char buf[MAX_TMPBUF]; 1653 const char *val; 1654 int rc = 0; 1655 struct spdk_iscsi_portal *portal = conn->portal; 1656 1657 /* declarative parameters */ 1658 if (target != NULL) { 1659 pthread_mutex_lock(&target->mutex); 1660 if (target->alias != NULL) 1661 snprintf(buf, sizeof buf, "%s", target->alias); 1662 else 1663 snprintf(buf, sizeof buf, "%s", ""); 1664 pthread_mutex_unlock(&target->mutex); 1665 rc = spdk_iscsi_param_set(conn->sess->params, "TargetAlias", buf); 1666 if (rc < 0) { 1667 SPDK_ERRLOG("iscsi_param_set() failed\n"); 1668 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1669 } 1670 } 1671 snprintf(buf, sizeof buf, "%s:%s,%d", portal->host, portal->port, 1672 portal->group->tag); 1673 rc = spdk_iscsi_param_set(conn->sess->params, "TargetAddress", buf); 1674 if (rc < 0) { 1675 SPDK_ERRLOG("iscsi_param_set() failed\n"); 1676 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1677 } 1678 snprintf(buf, sizeof buf, "%d", portal->group->tag); 1679 rc = spdk_iscsi_param_set(conn->sess->params, "TargetPortalGroupTag", 1680 buf); 1681 if (rc < 0) { 1682 SPDK_ERRLOG("iscsi_param_set() failed\n"); 1683 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1684 } 1685 1686 /* write in response */ 1687 if (target != NULL) { 1688 val = spdk_iscsi_param_get_val(conn->sess->params, "TargetAlias"); 1689 if (val != NULL && strlen(val) != 0) 1690 rsp_pdu->data_segment_len = spdk_iscsi_append_param(conn, 1691 "TargetAlias", 1692 rsp_pdu->data, 1693 alloc_len, 1694 rsp_pdu->data_segment_len); 1695 1696 if (session_type == SESSION_TYPE_DISCOVERY) 1697 rsp_pdu->data_segment_len = spdk_iscsi_append_param(conn, 1698 "TargetAddress", 1699 rsp_pdu->data, 1700 alloc_len, 1701 rsp_pdu->data_segment_len); 1702 1703 rsp_pdu->data_segment_len = spdk_iscsi_append_param(conn, 1704 "TargetPortalGroupTag", 1705 rsp_pdu->data, 1706 alloc_len, 1707 rsp_pdu->data_segment_len); 1708 } 1709 1710 return rc; 1711 1712 } 1713 1714 1715 1716 /* 1717 * This function is used to handle the login of iscsi initiator when there is 1718 * no session 1719 * return: 1720 * 0, success; 1721 * SPDK_ISCSI_LOGIN_ERROR_PARAMETER, parameter error; 1722 * SPDK_ISCSI_LOGIN_ERROR_RESPONSE, used to notify the login fail. 1723 */ 1724 static int 1725 spdk_iscsi_op_login_phase_none(struct spdk_iscsi_conn *conn, 1726 struct spdk_iscsi_pdu *rsp_pdu, 1727 struct iscsi_param *params, 1728 int alloc_len, int cid) 1729 { 1730 enum session_type session_type; 1731 char initiator_port_name[MAX_INITIATOR_NAME]; 1732 struct iscsi_bhs_login_rsp *rsph; 1733 struct spdk_iscsi_tgt_node *target = NULL; 1734 int rc = 0; 1735 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1736 1737 conn->target = NULL; 1738 conn->dev = NULL; 1739 1740 rc = spdk_iscsi_op_login_initialize_port(conn, rsp_pdu, 1741 initiator_port_name, 1742 MAX_INITIATOR_NAME, 1743 params); 1744 if (rc < 0) 1745 return rc; 1746 1747 rc = spdk_iscsi_op_login_session_type(conn, rsp_pdu, &session_type, 1748 params); 1749 if (rc < 0) 1750 return rc; 1751 1752 /* Target Name and Port */ 1753 if (session_type == SESSION_TYPE_NORMAL) { 1754 rc = spdk_iscsi_op_login_session_normal(conn, rsp_pdu, 1755 initiator_port_name, 1756 params, &target, cid); 1757 if (rc < 0) 1758 return rc; 1759 1760 } else if (session_type == SESSION_TYPE_DISCOVERY) { 1761 target = NULL; 1762 rsph->tsih = 0; 1763 1764 /* force target flags */ 1765 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1766 rc = spdk_iscsi_op_login_session_discovery_chap(conn); 1767 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1768 if (rc < 0) 1769 return rc; 1770 } else { 1771 SPDK_ERRLOG("unknown session type\n"); 1772 /* Missing parameter */ 1773 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1774 rsph->status_detail = ISCSI_LOGIN_MISSING_PARMS; 1775 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1776 } 1777 1778 rc = spdk_iscsi_op_login_set_conn_info(conn, rsp_pdu, 1779 initiator_port_name, 1780 session_type, target, cid); 1781 if (rc < 0) 1782 return rc; 1783 1784 /* limit conns on discovery session */ 1785 if (session_type == SESSION_TYPE_DISCOVERY) { 1786 conn->sess->MaxConnections = 1; 1787 rc = spdk_iscsi_param_set_int(conn->sess->params, 1788 "MaxConnections", 1789 conn->sess->MaxConnections); 1790 if (rc < 0) { 1791 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 1792 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1793 } 1794 } 1795 1796 rc = spdk_iscsi_op_login_set_target_info(conn, rsp_pdu, session_type, 1797 alloc_len, target); 1798 if (rc < 0) 1799 return rc; 1800 1801 return rc; 1802 1803 1804 } 1805 1806 /* 1807 * The function which is used to initalize the internal response data 1808 * structure of iscsi login function. 1809 * return: 1810 * 0, success; 1811 * otherwise, error; 1812 */ 1813 static int 1814 spdk_iscsi_op_login_rsp_init(struct spdk_iscsi_conn *conn, 1815 struct spdk_iscsi_pdu *pdu, struct spdk_iscsi_pdu *rsp_pdu, 1816 struct iscsi_param **params, int *alloc_len, int *cid) 1817 { 1818 1819 struct iscsi_bhs_login_req *reqh; 1820 struct iscsi_bhs_login_rsp *rsph; 1821 int rc; 1822 1823 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1824 rsph->opcode = ISCSI_OP_LOGIN_RSP; 1825 rsph->status_class = ISCSI_CLASS_SUCCESS; 1826 rsph->status_detail = ISCSI_LOGIN_ACCEPT; 1827 rsp_pdu->data_segment_len = 0; 1828 1829 /* Default MaxRecvDataSegmentLength - RFC3720(12.12) */ 1830 if (conn->MaxRecvDataSegmentLength < 8192) { 1831 *alloc_len = 8192; 1832 } else { 1833 *alloc_len = conn->MaxRecvDataSegmentLength; 1834 } 1835 1836 rsp_pdu->data = malloc(*alloc_len); 1837 if (!rsp_pdu->data) { 1838 perror("data"); 1839 return -ENOMEM; 1840 } 1841 1842 memset(rsp_pdu->data, 0, *alloc_len); 1843 1844 reqh = (struct iscsi_bhs_login_req *)&pdu->bhs; 1845 rsph->flags |= (reqh->flags & ISCSI_LOGIN_TRANSIT); 1846 rsph->flags |= (reqh->flags & ISCSI_LOGIN_CONTINUE); 1847 rsph->flags |= (reqh->flags & ISCSI_LOGIN_CURRENT_STAGE_MASK); 1848 if (ISCSI_BHS_LOGIN_GET_TBIT(rsph->flags)) 1849 rsph->flags |= (reqh->flags & ISCSI_LOGIN_NEXT_STAGE_MASK); 1850 1851 /* We don't need to convert from network byte order. Just store it */ 1852 memcpy(&rsph->isid, reqh->isid, 6); 1853 rsph->tsih = reqh->tsih; 1854 rsph->itt = reqh->itt; 1855 rsp_pdu->cmd_sn = from_be32(&reqh->cmd_sn); 1856 *cid = from_be16(&reqh->cid); 1857 1858 if (rsph->tsih) 1859 rsph->stat_sn = reqh->exp_stat_sn; 1860 1861 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "PDU", (uint8_t *)&pdu->bhs, ISCSI_BHS_LEN); 1862 1863 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 1864 "T=%d, C=%d, CSG=%d, NSG=%d, Min=%d, Max=%d, ITT=%x\n", 1865 ISCSI_BHS_LOGIN_GET_TBIT(rsph->flags), 1866 ISCSI_BHS_LOGIN_GET_CBIT(rsph->flags), 1867 ISCSI_BHS_LOGIN_GET_CSG(rsph->flags), 1868 ISCSI_BHS_LOGIN_GET_NSG(rsph->flags), 1869 reqh->version_min, reqh->version_max, from_be32(&rsph->itt)); 1870 1871 if (conn->sess != NULL) { 1872 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 1873 "CmdSN=%u, ExpStatSN=%u, StatSN=%u, ExpCmdSN=%u," 1874 "MaxCmdSN=%u\n", rsp_pdu->cmd_sn, 1875 from_be32(&rsph->stat_sn), conn->StatSN, 1876 conn->sess->ExpCmdSN, 1877 conn->sess->MaxCmdSN); 1878 } else { 1879 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 1880 "CmdSN=%u, ExpStatSN=%u, StatSN=%u\n", 1881 rsp_pdu->cmd_sn, from_be32(&rsph->stat_sn), 1882 conn->StatSN); 1883 } 1884 1885 if (ISCSI_BHS_LOGIN_GET_TBIT(rsph->flags) && 1886 ISCSI_BHS_LOGIN_GET_CBIT(rsph->flags)) { 1887 SPDK_ERRLOG("transit error\n"); 1888 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1889 } 1890 /* make sure reqh->version_max < ISCSI_VERSION */ 1891 if (reqh->version_min > ISCSI_VERSION) { 1892 SPDK_ERRLOG("unsupported version %d/%d\n", reqh->version_min, 1893 reqh->version_max); 1894 /* Unsupported version */ 1895 /* set all reserved flag to zero */ 1896 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1897 rsph->status_detail = ISCSI_LOGIN_UNSUPPORTED_VERSION; 1898 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1899 } 1900 1901 if ((ISCSI_BHS_LOGIN_GET_NSG(rsph->flags) == ISCSI_NSG_RESERVED_CODE) && 1902 ISCSI_BHS_LOGIN_GET_TBIT(rsph->flags)) { 1903 /* set NSG to zero */ 1904 rsph->flags &= ~ISCSI_LOGIN_NEXT_STAGE_MASK; 1905 /* also set other bits to zero */ 1906 rsph->flags &= ~ISCSI_LOGIN_TRANSIT; 1907 rsph->flags &= ~ISCSI_LOGIN_CURRENT_STAGE_MASK; 1908 SPDK_ERRLOG("Received reserved NSG code: %d\n", ISCSI_NSG_RESERVED_CODE); 1909 /* Initiator error */ 1910 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1911 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 1912 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1913 } 1914 1915 /* store incoming parameters */ 1916 rc = spdk_iscsi_parse_params(params, pdu->data, 1917 pdu->data_segment_len, ISCSI_BHS_LOGIN_GET_CBIT(reqh->flags), 1918 &conn->partial_text_parameter); 1919 if (rc < 0) { 1920 SPDK_ERRLOG("iscsi_parse_params() failed\n"); 1921 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1922 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 1923 return SPDK_ISCSI_LOGIN_ERROR_PARAMETER; 1924 } 1925 return 0; 1926 } 1927 1928 1929 /* 1930 * This function is used to set the csg bit case in rsp 1931 * return: 1932 * 0, success 1933 * otherwise: error 1934 */ 1935 static int 1936 spdk_iscsi_op_login_rsp_handle_csg_bit(struct spdk_iscsi_conn *conn, 1937 struct spdk_iscsi_pdu *rsp_pdu, 1938 struct iscsi_param *params, int alloc_len) 1939 { 1940 const char *auth_method; 1941 int rc; 1942 struct iscsi_bhs_login_rsp *rsph; 1943 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 1944 1945 switch (ISCSI_BHS_LOGIN_GET_CSG(rsph->flags)) { 1946 case ISCSI_SECURITY_NEGOTIATION_PHASE: 1947 /* SecurityNegotiation */ 1948 auth_method = spdk_iscsi_param_get_val(conn->params, "AuthMethod"); 1949 if (auth_method == NULL) { 1950 SPDK_ERRLOG("AuthMethod is empty\n"); 1951 /* Missing parameter */ 1952 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1953 rsph->status_detail = ISCSI_LOGIN_MISSING_PARMS; 1954 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1955 } 1956 if (strcasecmp(auth_method, "None") == 0) 1957 conn->authenticated = 1; 1958 else { 1959 rc = spdk_iscsi_auth_params(conn, params, auth_method, 1960 rsp_pdu->data, alloc_len, 1961 rsp_pdu->data_segment_len); 1962 if (rc < 0) { 1963 SPDK_ERRLOG("iscsi_auth_params() failed\n"); 1964 /* Authentication failure */ 1965 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1966 rsph->status_detail = ISCSI_LOGIN_AUTHENT_FAIL; 1967 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1968 } 1969 rsp_pdu->data_segment_len = rc; 1970 if (conn->authenticated == 0) { 1971 /* not complete */ 1972 rsph->flags &= ~ISCSI_LOGIN_TRANSIT; 1973 } else { 1974 if (conn->auth.chap_phase != 1975 ISCSI_CHAP_PHASE_END) { 1976 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 1977 "CHAP phase not " 1978 "complete"); 1979 } 1980 } 1981 1982 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "Negotiated Auth Params", 1983 rsp_pdu->data, rsp_pdu->data_segment_len); 1984 } 1985 break; 1986 1987 case ISCSI_OPERATIONAL_NEGOTIATION_PHASE: 1988 /* LoginOperationalNegotiation */ 1989 if (conn->state == ISCSI_CONN_STATE_INVALID) { 1990 if (conn->req_auth) { 1991 /* Authentication failure */ 1992 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 1993 rsph->status_detail = ISCSI_LOGIN_AUTHENT_FAIL; 1994 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 1995 } else { 1996 /* AuthMethod=None */ 1997 conn->authenticated = 1; 1998 } 1999 } 2000 if (conn->authenticated == 0) { 2001 SPDK_ERRLOG("authentication error\n"); 2002 /* Authentication failure */ 2003 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 2004 rsph->status_detail = ISCSI_LOGIN_AUTHENT_FAIL; 2005 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 2006 } 2007 break; 2008 2009 case ISCSI_FULL_FEATURE_PHASE: 2010 /* FullFeaturePhase */ 2011 SPDK_ERRLOG("XXX Login in FullFeaturePhase\n"); 2012 /* Initiator error */ 2013 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 2014 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 2015 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 2016 2017 default: 2018 SPDK_ERRLOG("unknown stage\n"); 2019 /* Initiator error */ 2020 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 2021 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 2022 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 2023 } 2024 2025 return 0; 2026 2027 } 2028 2029 /* This function is used to notify the session info 2030 * return 2031 * 0: success 2032 * otherwise: error 2033 */ 2034 static int 2035 spdk_iscsi_op_login_notify_session_info(struct spdk_iscsi_conn *conn, 2036 struct spdk_iscsi_pdu *rsp_pdu) 2037 { 2038 struct spdk_iscsi_portal *portal = conn->portal; 2039 struct iscsi_bhs_login_rsp *rsph; 2040 2041 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 2042 if (conn->sess->session_type == SESSION_TYPE_NORMAL) { 2043 /* normal session */ 2044 SPDK_NOTICELOG("Login from %s (%s) on %s tgt_node%d" 2045 " (%s:%s,%d), ISID=%"PRIx64", TSIH=%u," 2046 " CID=%u, HeaderDigest=%s, DataDigest=%s\n", 2047 conn->initiator_name, conn->initiator_addr, 2048 conn->target->name, conn->target->num, 2049 portal->host, portal->port, portal->group->tag, 2050 conn->sess->isid, conn->sess->tsih, conn->cid, 2051 (spdk_iscsi_param_eq_val(conn->params, "HeaderDigest", "CRC32C") 2052 ? "on" : "off"), 2053 (spdk_iscsi_param_eq_val(conn->params, "DataDigest", "CRC32C") 2054 ? "on" : "off")); 2055 } else if (conn->sess->session_type == SESSION_TYPE_DISCOVERY) { 2056 /* discovery session */ 2057 SPDK_NOTICELOG("Login(discovery) from %s (%s) on" 2058 " (%s:%s,%d), ISID=%"PRIx64", TSIH=%u," 2059 " CID=%u, HeaderDigest=%s, DataDigest=%s\n", 2060 conn->initiator_name, conn->initiator_addr, 2061 portal->host, portal->port, portal->group->tag, 2062 conn->sess->isid, conn->sess->tsih, conn->cid, 2063 (spdk_iscsi_param_eq_val(conn->params, "HeaderDigest", "CRC32C") 2064 ? "on" : "off"), 2065 (spdk_iscsi_param_eq_val(conn->params, "DataDigest", "CRC32C") 2066 ? "on" : "off")); 2067 } else { 2068 SPDK_ERRLOG("unknown session type\n"); 2069 /* Initiator error */ 2070 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 2071 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 2072 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 2073 } 2074 2075 return 0; 2076 2077 } 2078 2079 /* 2080 * This function is to handle the tbit cases 2081 * return 2082 * 0: success 2083 * otherwise error 2084 */ 2085 static int 2086 spdk_iscsi_op_login_rsp_handle_t_bit(struct spdk_iscsi_conn *conn, 2087 struct spdk_iscsi_pdu *rsp_pdu) 2088 2089 { 2090 int rc; 2091 struct iscsi_bhs_login_rsp *rsph; 2092 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 2093 2094 switch (ISCSI_BHS_LOGIN_GET_NSG(rsph->flags)) { 2095 case ISCSI_SECURITY_NEGOTIATION_PHASE: 2096 /* SecurityNegotiation */ 2097 conn->login_phase = ISCSI_SECURITY_NEGOTIATION_PHASE; 2098 break; 2099 2100 case ISCSI_OPERATIONAL_NEGOTIATION_PHASE: 2101 /* LoginOperationalNegotiation */ 2102 conn->login_phase = ISCSI_OPERATIONAL_NEGOTIATION_PHASE; 2103 break; 2104 2105 case ISCSI_FULL_FEATURE_PHASE: 2106 /* FullFeaturePhase */ 2107 conn->login_phase = ISCSI_FULL_FEATURE_PHASE; 2108 to_be16(&rsph->tsih, conn->sess->tsih); 2109 2110 rc = spdk_iscsi_op_login_notify_session_info(conn, rsp_pdu); 2111 if (rc < 0) 2112 return rc; 2113 2114 conn->full_feature = 1; 2115 break; 2116 2117 default: 2118 SPDK_ERRLOG("unknown stage\n"); 2119 /* Initiator error */ 2120 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 2121 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 2122 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 2123 } 2124 2125 return 0; 2126 } 2127 2128 2129 2130 /* 2131 * This function is used to set the values of the internal data structure used 2132 * by spdk_iscsi_op_login function 2133 * return: 2134 * 0, used to notify the a successful login 2135 * SPDK_ISCSI_LOGIN_ERROR_RESPONSE, used to notify a failure login. 2136 */ 2137 static int 2138 spdk_iscsi_op_login_rsp_handle(struct spdk_iscsi_conn *conn, 2139 struct spdk_iscsi_pdu *rsp_pdu, struct iscsi_param **params, 2140 int alloc_len) 2141 { 2142 int rc = 0; 2143 struct iscsi_bhs_login_rsp *rsph; 2144 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 2145 2146 /* negotiate parameters */ 2147 rc = spdk_iscsi_negotiate_params(conn, params, rsp_pdu->data, alloc_len, 2148 rsp_pdu->data_segment_len); 2149 if (rc < 0) { 2150 /* 2151 * spdk_iscsi_negotiate_params just returns -1 on failure, 2152 * so translate this into meaningful response codes and 2153 * return values. 2154 */ 2155 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 2156 rsph->status_detail = ISCSI_LOGIN_INITIATOR_ERROR; 2157 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 2158 } 2159 2160 rsp_pdu->data_segment_len = rc; 2161 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "Negotiated Params", rsp_pdu->data, rc); 2162 2163 /* handle the CSG bit case */ 2164 rc = spdk_iscsi_op_login_rsp_handle_csg_bit(conn, rsp_pdu, *params, 2165 alloc_len); 2166 if (rc < 0) 2167 return rc; 2168 2169 /* handle the T bit case */ 2170 if (ISCSI_BHS_LOGIN_GET_TBIT(rsph->flags)) 2171 rc = spdk_iscsi_op_login_rsp_handle_t_bit(conn, rsp_pdu); 2172 2173 return rc; 2174 } 2175 2176 static int 2177 spdk_iscsi_op_login(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 2178 { 2179 int rc; 2180 struct spdk_iscsi_pdu *rsp_pdu; 2181 struct iscsi_param *params = NULL; 2182 struct iscsi_param **params_p = ¶ms; 2183 int alloc_len; 2184 int cid; 2185 2186 2187 if (conn->full_feature && conn->sess != NULL && 2188 conn->sess->session_type == SESSION_TYPE_DISCOVERY) { 2189 return SPDK_ISCSI_CONNECTION_FATAL; 2190 } 2191 2192 2193 rsp_pdu = spdk_get_pdu(); 2194 rc = spdk_iscsi_op_login_rsp_init(conn, pdu, rsp_pdu, params_p, 2195 &alloc_len, &cid); 2196 if (rc == SPDK_ISCSI_LOGIN_ERROR_RESPONSE || rc == SPDK_ISCSI_LOGIN_ERROR_PARAMETER) { 2197 spdk_iscsi_op_login_response(conn, rsp_pdu, *params_p); 2198 return rc; 2199 } 2200 2201 /* For other values, we need to directly return */ 2202 if (rc < 0) { 2203 spdk_put_pdu(rsp_pdu); 2204 return rc; 2205 } 2206 2207 if (conn->state == ISCSI_CONN_STATE_INVALID) { 2208 rc = spdk_iscsi_op_login_phase_none(conn, rsp_pdu, *params_p, 2209 alloc_len, cid); 2210 if (rc == SPDK_ISCSI_LOGIN_ERROR_RESPONSE || rc == SPDK_ISCSI_LOGIN_ERROR_PARAMETER) { 2211 spdk_iscsi_op_login_response(conn, rsp_pdu, *params_p); 2212 return rc; 2213 } 2214 } 2215 2216 rc = spdk_iscsi_op_login_rsp_handle(conn, rsp_pdu, params_p, alloc_len); 2217 if (rc == SPDK_ISCSI_LOGIN_ERROR_RESPONSE) { 2218 spdk_iscsi_op_login_response(conn, rsp_pdu, *params_p); 2219 return rc; 2220 } 2221 2222 rc = spdk_iscsi_op_login_response(conn, rsp_pdu, *params_p); 2223 2224 if (rc == 0) { 2225 conn->state = ISCSI_CONN_STATE_RUNNING; 2226 } else { 2227 SPDK_ERRLOG("login error - connection will be destroyed\n"); 2228 } 2229 2230 return rc; 2231 2232 } 2233 2234 static int 2235 spdk_iscsi_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 2236 { 2237 struct iscsi_param *params = NULL; 2238 struct iscsi_param **params_p = ¶ms; 2239 struct spdk_iscsi_pdu *rsp_pdu; 2240 uint8_t *data; 2241 uint64_t lun; 2242 uint32_t task_tag; 2243 uint32_t CmdSN; 2244 uint32_t ExpStatSN; 2245 const char *val; 2246 int F_bit, C_bit; 2247 int data_len; 2248 int alloc_len; 2249 int rc; 2250 struct iscsi_bhs_text_req *reqh; 2251 struct iscsi_bhs_text_resp *rsph; 2252 2253 data_len = 0; 2254 alloc_len = conn->MaxRecvDataSegmentLength; 2255 2256 reqh = (struct iscsi_bhs_text_req *)&pdu->bhs; 2257 2258 F_bit = !!(reqh->flags & ISCSI_FLAG_FINAL); 2259 C_bit = !!(reqh->flags & ISCSI_TEXT_CONTINUE); 2260 lun = from_be64(&reqh->lun); 2261 task_tag = from_be32(&reqh->itt); 2262 CmdSN = from_be32(&reqh->cmd_sn); 2263 pdu->cmd_sn = CmdSN; 2264 ExpStatSN = from_be32(&reqh->exp_stat_sn); 2265 2266 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "I=%d, F=%d, C=%d, ITT=%x, TTT=%x\n", 2267 reqh->immediate, F_bit, C_bit, task_tag, from_be32(&reqh->ttt)); 2268 2269 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 2270 "CmdSN=%u, ExpStatSN=%u, StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n", 2271 CmdSN, ExpStatSN, conn->StatSN, conn->sess->ExpCmdSN, 2272 conn->sess->MaxCmdSN); 2273 2274 if (ExpStatSN != conn->StatSN) { 2275 #if 0 2276 SPDK_ERRLOG("StatSN(%u) error\n", ExpStatSN); 2277 return -1; 2278 #else 2279 /* StarPort have a bug */ 2280 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "StatSN(%u) rewound\n", ExpStatSN); 2281 conn->StatSN = ExpStatSN; 2282 #endif 2283 } 2284 2285 if (F_bit && C_bit) { 2286 SPDK_ERRLOG("final and continue\n"); 2287 return -1; 2288 } 2289 2290 /* 2291 * If this is the first text op in a sequence, save the ITT so we can 2292 * compare it against the ITT for subsequent ops in the same sequence. 2293 * If a subsequent text op in same sequence has a different ITT, reject 2294 * that PDU. 2295 */ 2296 if (conn->sess->current_text_itt == 0xffffffffU) { 2297 conn->sess->current_text_itt = task_tag; 2298 } else if (conn->sess->current_text_itt != task_tag) { 2299 SPDK_ERRLOG("The correct itt is %u, and the current itt is %u...\n", 2300 conn->sess->current_text_itt, task_tag); 2301 return spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 2302 } 2303 2304 /* store incoming parameters */ 2305 rc = spdk_iscsi_parse_params(¶ms, pdu->data, 2306 pdu->data_segment_len, C_bit, &conn->partial_text_parameter); 2307 if (rc < 0) { 2308 SPDK_ERRLOG("iscsi_parse_params() failed\n"); 2309 spdk_iscsi_param_free(params); 2310 return -1; 2311 } 2312 2313 data = malloc(alloc_len); 2314 if (!data) { 2315 perror("data"); 2316 spdk_iscsi_param_free(params); 2317 return -ENOMEM; 2318 } 2319 2320 memset(data, 0, alloc_len); 2321 2322 /* negotiate parameters */ 2323 data_len = spdk_iscsi_negotiate_params(conn, params_p, 2324 data, alloc_len, data_len); 2325 if (data_len < 0) { 2326 SPDK_ERRLOG("spdk_iscsi_negotiate_params() failed\n"); 2327 spdk_iscsi_param_free(*params_p); 2328 free(data); 2329 return -1; 2330 } 2331 2332 /* sendtargets is special case */ 2333 val = spdk_iscsi_param_get_val(*params_p, "SendTargets"); 2334 if (val != NULL) { 2335 if (spdk_iscsi_param_eq_val(conn->sess->params, 2336 "SessionType", "Discovery")) { 2337 if (strcasecmp(val, "") == 0) 2338 val = "ALL"; 2339 2340 data_len = spdk_iscsi_send_tgts(conn, 2341 conn->initiator_name, 2342 conn->initiator_addr, 2343 val, data, alloc_len, 2344 data_len); 2345 } else { 2346 if (strcasecmp(val, "") == 0) 2347 val = conn->target->name; 2348 2349 if (strcasecmp(val, "ALL") == 0) { 2350 /* not in discovery session */ 2351 data_len = spdk_iscsi_append_text(conn, 2352 "SendTargets", 2353 "Reject", data, 2354 alloc_len, 2355 data_len); 2356 } else { 2357 data_len = spdk_iscsi_send_tgts(conn, 2358 conn->initiator_name, 2359 conn->initiator_addr, 2360 val, data, alloc_len, 2361 data_len); 2362 } 2363 } 2364 } else { 2365 if (spdk_iscsi_param_eq_val(conn->sess->params, 2366 "SessionType", "Discovery")) { 2367 free(data); 2368 return SPDK_ISCSI_CONNECTION_FATAL; 2369 } 2370 } 2371 2372 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "Negotiated Params", data, data_len); 2373 2374 /* response PDU */ 2375 rsp_pdu = spdk_get_pdu(); 2376 rsph = (struct iscsi_bhs_text_resp *)&rsp_pdu->bhs; 2377 2378 rsp_pdu->data = data; 2379 rsph->opcode = ISCSI_OP_TEXT_RSP; 2380 2381 if (F_bit) 2382 rsph->flags |= ISCSI_FLAG_FINAL; 2383 2384 if (C_bit) 2385 rsph->flags |= ISCSI_TEXT_CONTINUE; 2386 2387 DSET24(rsph->data_segment_len, data_len); 2388 to_be64(&rsph->lun, lun); 2389 to_be32(&rsph->itt, task_tag); 2390 2391 if (F_bit) { 2392 rsph->ttt = 0xffffffffU; 2393 conn->sess->current_text_itt = 0xffffffffU; 2394 } else { 2395 to_be32(&rsph->ttt, 1 + conn->id); 2396 } 2397 2398 to_be32(&rsph->stat_sn, conn->StatSN); 2399 conn->StatSN++; 2400 2401 if (reqh->immediate == 0) { 2402 conn->sess->MaxCmdSN++; 2403 } 2404 2405 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 2406 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 2407 2408 spdk_iscsi_write_pdu(conn, rsp_pdu); 2409 2410 /* update internal variables */ 2411 rc = spdk_iscsi_copy_param2var(conn); 2412 if (rc < 0) { 2413 SPDK_ERRLOG("spdk_iscsi_copy_param2var() failed\n"); 2414 spdk_iscsi_param_free(*params_p); 2415 return -1; 2416 } 2417 2418 /* check value */ 2419 rc = spdk_iscsi_check_values(conn); 2420 if (rc < 0) { 2421 SPDK_ERRLOG("iscsi_check_values() failed\n"); 2422 spdk_iscsi_param_free(*params_p); 2423 return -1; 2424 } 2425 2426 spdk_iscsi_param_free(*params_p); 2427 return 0; 2428 } 2429 2430 static int 2431 spdk_iscsi_op_logout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 2432 { 2433 char buf[MAX_TMPBUF]; 2434 struct spdk_iscsi_pdu *rsp_pdu; 2435 uint32_t task_tag; 2436 uint32_t CmdSN; 2437 uint32_t ExpStatSN; 2438 int response; 2439 struct iscsi_bhs_logout_req *reqh; 2440 struct iscsi_bhs_logout_resp *rsph; 2441 uint16_t cid; 2442 2443 reqh = (struct iscsi_bhs_logout_req *)&pdu->bhs; 2444 2445 cid = from_be16(&reqh->cid); 2446 task_tag = from_be32(&reqh->itt); 2447 CmdSN = from_be32(&reqh->cmd_sn); 2448 pdu->cmd_sn = CmdSN; 2449 ExpStatSN = from_be32(&reqh->exp_stat_sn); 2450 2451 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "reason=%d, ITT=%x, cid=%d\n", 2452 reqh->reason, task_tag, cid); 2453 2454 if (reqh->reason != 0 && conn->sess->session_type == SESSION_TYPE_DISCOVERY) { 2455 SPDK_ERRLOG("only logout with close the session reason can be in discovery session"); 2456 return SPDK_ISCSI_CONNECTION_FATAL; 2457 2458 } 2459 2460 2461 if (conn->sess != NULL) { 2462 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 2463 "CmdSN=%u, ExpStatSN=%u, StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n", 2464 CmdSN, ExpStatSN, conn->StatSN, 2465 conn->sess->ExpCmdSN, conn->sess->MaxCmdSN); 2466 2467 if (CmdSN != conn->sess->ExpCmdSN) { 2468 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "CmdSN(%u) might have dropped\n", CmdSN); 2469 /* ignore error */ 2470 } 2471 } else { 2472 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 2473 "CmdSN=%u, ExpStatSN=%u, StatSN=%u\n", 2474 CmdSN, ExpStatSN, conn->StatSN); 2475 } 2476 2477 if (ExpStatSN != conn->StatSN) { 2478 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "StatSN(%u/%u) might have dropped\n", 2479 ExpStatSN, conn->StatSN); 2480 /* ignore error */ 2481 } 2482 2483 if (conn->id == cid) { 2484 response = 0; // connection or session closed successfully 2485 spdk_iscsi_conn_logout(conn); 2486 } else { 2487 response = 1; 2488 } 2489 2490 /* response PDU */ 2491 rsp_pdu = spdk_get_pdu(); 2492 rsph = (struct iscsi_bhs_logout_resp *)&rsp_pdu->bhs; 2493 rsp_pdu->data = NULL; 2494 rsph->opcode = ISCSI_OP_LOGOUT_RSP; 2495 rsph->flags |= 0x80; /* bit 0 must be 1 */ 2496 rsph->response = response; 2497 DSET24(rsph->data_segment_len, 0); 2498 to_be32(&rsph->itt, task_tag); 2499 2500 if (conn->sess != NULL) { 2501 to_be32(&rsph->stat_sn, conn->StatSN); 2502 conn->StatSN++; 2503 2504 if (conn->sess->connections == 1) { 2505 conn->sess->MaxCmdSN++; 2506 } 2507 2508 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 2509 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 2510 } else { 2511 to_be32(&rsph->stat_sn, conn->StatSN); 2512 conn->StatSN++; 2513 to_be32(&rsph->exp_cmd_sn, CmdSN); 2514 to_be32(&rsph->max_cmd_sn, CmdSN); 2515 } 2516 2517 rsph->time_2_wait = 0; 2518 rsph->time_2_retain = 0; 2519 2520 spdk_iscsi_write_pdu(conn, rsp_pdu); 2521 2522 if (conn->sess == NULL) { 2523 /* 2524 * login failed but initiator still sent a logout rather than 2525 * just closing the TCP connection. 2526 */ 2527 snprintf(buf, sizeof buf, "Logout(login failed) from %s (%s) on" 2528 " (%s:%s,%d)\n", 2529 conn->initiator_name, conn->initiator_addr, 2530 conn->portal_host, conn->portal_port, conn->pg_tag); 2531 } else if (spdk_iscsi_param_eq_val(conn->sess->params, "SessionType", "Normal")) { 2532 snprintf(buf, sizeof buf, "Logout from %s (%s) on %s tgt_node%d" 2533 " (%s:%s,%d), ISID=%"PRIx64", TSIH=%u," 2534 " CID=%u, HeaderDigest=%s, DataDigest=%s\n", 2535 conn->initiator_name, conn->initiator_addr, 2536 conn->target->name, conn->target->num, 2537 conn->portal_host, conn->portal_port, conn->pg_tag, 2538 conn->sess->isid, conn->sess->tsih, conn->cid, 2539 (spdk_iscsi_param_eq_val(conn->params, "HeaderDigest", "CRC32C") 2540 ? "on" : "off"), 2541 (spdk_iscsi_param_eq_val(conn->params, "DataDigest", "CRC32C") 2542 ? "on" : "off")); 2543 } else { 2544 /* discovery session */ 2545 snprintf(buf, sizeof buf, "Logout(discovery) from %s (%s) on" 2546 " (%s:%s,%d), ISID=%"PRIx64", TSIH=%u," 2547 " CID=%u, HeaderDigest=%s, DataDigest=%s\n", 2548 conn->initiator_name, conn->initiator_addr, 2549 conn->portal_host, conn->portal_port, conn->pg_tag, 2550 conn->sess->isid, conn->sess->tsih, conn->cid, 2551 (spdk_iscsi_param_eq_val(conn->params, "HeaderDigest", "CRC32C") 2552 ? "on" : "off"), 2553 (spdk_iscsi_param_eq_val(conn->params, "DataDigest", "CRC32C") 2554 ? "on" : "off")); 2555 } 2556 2557 SPDK_NOTICELOG("%s", buf); 2558 2559 return 0; 2560 } 2561 2562 /* This function returns the spdk_scsi_task by searching the snack list via 2563 * task transfertag and the pdu's opcode 2564 */ 2565 static struct spdk_iscsi_task * 2566 spdk_get_scsi_task_from_ttt(struct spdk_iscsi_conn *conn, 2567 uint32_t transfer_tag) 2568 { 2569 struct spdk_iscsi_pdu *pdu; 2570 struct iscsi_bhs_data_in *datain_bhs; 2571 struct spdk_iscsi_task *task = NULL; 2572 2573 TAILQ_FOREACH(pdu, &conn->snack_pdu_list, tailq) { 2574 if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) { 2575 datain_bhs = (struct iscsi_bhs_data_in *)&pdu->bhs; 2576 if (from_be32(&datain_bhs->ttt) == transfer_tag) { 2577 task = pdu->task; 2578 break; 2579 } 2580 } 2581 } 2582 2583 return task; 2584 } 2585 2586 /* This function returns the spdk_scsi_task by searching the snack list via 2587 * initiator task tag and the pdu's opcode 2588 */ 2589 static struct spdk_iscsi_task * 2590 spdk_get_scsi_task_from_itt(struct spdk_iscsi_conn *conn, 2591 uint32_t task_tag, enum iscsi_op opcode) 2592 { 2593 struct spdk_iscsi_pdu *pdu; 2594 struct spdk_iscsi_task *task = NULL; 2595 2596 TAILQ_FOREACH(pdu, &conn->snack_pdu_list, tailq) { 2597 if (pdu->bhs.opcode == opcode && 2598 pdu->task != NULL && 2599 pdu->task->tag == task_tag) { 2600 task = pdu->task; 2601 break; 2602 } 2603 } 2604 2605 return task; 2606 } 2607 2608 static int 2609 spdk_iscsi_send_datain(struct spdk_iscsi_conn *conn, 2610 struct spdk_iscsi_task *task, int datain_flag, 2611 int residual_len, int offset, int DataSN, int len) 2612 { 2613 struct spdk_iscsi_pdu *rsp_pdu; 2614 struct iscsi_bhs_data_in *rsph; 2615 uint32_t task_tag; 2616 uint32_t transfer_tag; 2617 int F_bit, U_bit, O_bit, S_bit; 2618 struct spdk_iscsi_task *primary; 2619 2620 primary = spdk_iscsi_task_get_primary(task); 2621 2622 /* DATA PDU */ 2623 rsp_pdu = spdk_get_pdu(); 2624 rsph = (struct iscsi_bhs_data_in *)&rsp_pdu->bhs; 2625 rsp_pdu->data = task->scsi.iovs[0].iov_base + offset; 2626 rsp_pdu->data_from_mempool = true; 2627 2628 task_tag = task->tag; 2629 transfer_tag = 0xffffffffU; 2630 2631 F_bit = datain_flag & ISCSI_FLAG_FINAL; 2632 O_bit = datain_flag & ISCSI_DATAIN_OVERFLOW; 2633 U_bit = datain_flag & ISCSI_DATAIN_UNDERFLOW; 2634 S_bit = datain_flag & ISCSI_DATAIN_STATUS; 2635 2636 /* 2637 * we need to hold onto this task/cmd because until the 2638 * PDU has been written out 2639 */ 2640 rsp_pdu->task = task; 2641 task->scsi.ref++; 2642 2643 rsph->opcode = ISCSI_OP_SCSI_DATAIN; 2644 2645 if (F_bit) 2646 rsph->flags |= ISCSI_FLAG_FINAL; 2647 2648 /* we leave the A_bit clear */ 2649 2650 if (F_bit && S_bit) { 2651 if (O_bit) 2652 rsph->flags |= ISCSI_DATAIN_OVERFLOW; 2653 2654 if (U_bit) 2655 rsph->flags |= ISCSI_DATAIN_UNDERFLOW; 2656 } 2657 2658 if (S_bit) { 2659 rsph->flags |= ISCSI_DATAIN_STATUS; 2660 rsph->status = task->scsi.status; 2661 } 2662 2663 DSET24(rsph->data_segment_len, len); 2664 2665 to_be32(&rsph->itt, task_tag); 2666 to_be32(&rsph->ttt, transfer_tag); 2667 2668 if (S_bit) { 2669 to_be32(&rsph->stat_sn, conn->StatSN); 2670 conn->StatSN++; 2671 } 2672 2673 if (F_bit && S_bit && !spdk_iscsi_task_is_immediate(primary)) 2674 conn->sess->MaxCmdSN++; 2675 2676 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 2677 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 2678 2679 to_be32(&rsph->data_sn, DataSN); 2680 2681 if (conn->sess->ErrorRecoveryLevel >= 1) 2682 primary->datain_datasn = DataSN; 2683 DataSN++; 2684 2685 if (task->scsi.parent) 2686 offset += primary->scsi.data_transferred; 2687 to_be32(&rsph->buffer_offset, (uint32_t)offset); 2688 2689 if (F_bit && S_bit) 2690 to_be32(&rsph->res_cnt, residual_len); 2691 2692 spdk_iscsi_write_pdu(conn, rsp_pdu); 2693 2694 return DataSN; 2695 } 2696 2697 static int 2698 spdk_iscsi_transfer_in(struct spdk_iscsi_conn *conn, 2699 struct spdk_iscsi_task *task) 2700 { 2701 uint32_t DataSN; 2702 int transfer_len; 2703 int data_len; 2704 int segment_len; 2705 int offset; 2706 int residual_len = 0; 2707 int sent_status; 2708 int len; 2709 int datain_flag = 0; 2710 int datain_seq_cnt; 2711 int i; 2712 int sequence_end; 2713 struct spdk_iscsi_task *primary; 2714 2715 primary = spdk_iscsi_task_get_primary(task); 2716 segment_len = conn->MaxRecvDataSegmentLength; 2717 data_len = task->scsi.data_transferred; 2718 transfer_len = task->scsi.length; 2719 2720 if (task->scsi.status != SPDK_SCSI_STATUS_GOOD) { 2721 if (task != primary) { 2722 conn->data_in_cnt--; 2723 /* Handle the case when primary task return success but the subtask failed */ 2724 if (primary->bytes_completed == primary->scsi.transfer_len && 2725 primary->scsi.status == SPDK_SCSI_STATUS_GOOD) { 2726 conn->data_in_cnt--; 2727 } 2728 } else { 2729 /* handle the case that it is a primary task which has subtasks */ 2730 if (primary->scsi.transfer_len != task->scsi.length) { 2731 conn->data_in_cnt--; 2732 } 2733 } 2734 2735 return 0; 2736 } 2737 2738 if (data_len < transfer_len) { 2739 /* underflow */ 2740 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Underflow %u/%u\n", 2741 data_len, transfer_len); 2742 residual_len = transfer_len - data_len; 2743 transfer_len = data_len; 2744 datain_flag |= ISCSI_DATAIN_UNDERFLOW; 2745 } else if (data_len > transfer_len) { 2746 /* overflow */ 2747 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Overflow %u/%u\n", 2748 data_len, transfer_len); 2749 residual_len = data_len - transfer_len; 2750 datain_flag |= ISCSI_DATAIN_OVERFLOW; 2751 } else { 2752 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Transfer %u\n", 2753 transfer_len); 2754 residual_len = 0; 2755 } 2756 2757 DataSN = primary->datain_datasn; 2758 sent_status = 0; 2759 2760 /* calculate the number of sequences for all data-in pdus */ 2761 datain_seq_cnt = 1 + ((transfer_len - 1) / (int)conn->sess->MaxBurstLength); 2762 for (i = 0; i < datain_seq_cnt; i++) { 2763 offset = i * conn->sess->MaxBurstLength; 2764 sequence_end = DMIN32(((i + 1) * conn->sess->MaxBurstLength), 2765 transfer_len); 2766 datain_flag &= ~ISCSI_FLAG_FINAL; 2767 datain_flag &= ~ISCSI_DATAIN_STATUS; 2768 2769 /* send data splitted by segment_len */ 2770 for (; offset < sequence_end; offset += segment_len) { 2771 len = DMIN32(segment_len, (sequence_end - offset)); 2772 2773 if (offset + len == sequence_end) { 2774 /* last PDU in a sequence */ 2775 datain_flag |= ISCSI_FLAG_FINAL; 2776 datain_flag &= ~ISCSI_DATAIN_STATUS; 2777 if (task->scsi.sense_data_len == 0) { 2778 switch (task->scsi.status) { 2779 case SPDK_SCSI_STATUS_GOOD: 2780 case SPDK_SCSI_STATUS_CONDITION_MET: 2781 case SPDK_SCSI_STATUS_INTERMEDIATE: 2782 case SPDK_SCSI_STATUS_INTERMEDIATE_CONDITION_MET: 2783 /* The last pdu in all data-in pdus */ 2784 if ((offset + len) == transfer_len && 2785 (primary->bytes_completed == 2786 primary->scsi.transfer_len)) { 2787 datain_flag |= ISCSI_DATAIN_STATUS; 2788 sent_status = 1; 2789 } 2790 } 2791 } 2792 } else { 2793 datain_flag &= ~ISCSI_FLAG_FINAL; 2794 datain_flag &= ~ISCSI_DATAIN_STATUS; 2795 } 2796 2797 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 2798 "Transfer=%d, Offset=%d, Len=%d\n", 2799 sequence_end, offset, len); 2800 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 2801 "StatSN=%u, DataSN=%u, Offset=%u, Len=%d\n", 2802 conn->StatSN, DataSN, offset, len); 2803 2804 DataSN = spdk_iscsi_send_datain(conn, task, datain_flag, 2805 residual_len, offset, 2806 DataSN, len); 2807 } 2808 } 2809 2810 if (task != primary) 2811 primary->scsi.data_transferred += task->scsi.data_transferred; 2812 primary->datain_datasn = DataSN; 2813 2814 if (sent_status) 2815 return 1; 2816 2817 return 0; 2818 } 2819 2820 /* 2821 * This function compare the input pdu's bhs with the pdu's bhs associated by 2822 * active_r2t_tasks and queued_r2t_tasks in a connection 2823 */ 2824 static bool 2825 spdk_iscsi_compare_pdu_bhs_within_existed_r2t_tasks(struct spdk_iscsi_conn *conn, 2826 struct spdk_iscsi_pdu *pdu) 2827 { 2828 struct spdk_iscsi_task *task; 2829 2830 TAILQ_FOREACH(task, &conn->active_r2t_tasks, link) { 2831 if (!memcmp(&pdu->bhs, spdk_iscsi_task_get_bhs(task), ISCSI_BHS_LEN)) 2832 return true; 2833 } 2834 2835 TAILQ_FOREACH(task, &conn->queued_r2t_tasks, link) { 2836 if (!memcmp(&pdu->bhs, spdk_iscsi_task_get_bhs(task), ISCSI_BHS_LEN)) 2837 return true; 2838 } 2839 2840 return false; 2841 } 2842 2843 static void spdk_iscsi_queue_task(struct spdk_iscsi_conn *conn, 2844 struct spdk_iscsi_task *task) 2845 { 2846 spdk_trace_record(TRACE_ISCSI_TASK_QUEUE, conn->id, task->scsi.length, 2847 (uintptr_t)task, (uintptr_t)task->pdu); 2848 spdk_scsi_dev_queue_task(conn->dev, &task->scsi); 2849 } 2850 2851 static void spdk_iscsi_queue_mgmt_task(struct spdk_iscsi_conn *conn, 2852 struct spdk_iscsi_task *task, 2853 enum spdk_scsi_task_func func) 2854 { 2855 spdk_scsi_dev_queue_mgmt_task(conn->dev, &task->scsi, func); 2856 } 2857 2858 int spdk_iscsi_conn_handle_queued_tasks(struct spdk_iscsi_conn *conn) 2859 { 2860 struct spdk_iscsi_task *task; 2861 2862 while (!TAILQ_EMPTY(&conn->queued_datain_tasks) && 2863 conn->data_in_cnt < MAX_LARGE_DATAIN_PER_CONNECTION) { 2864 task = TAILQ_FIRST(&conn->queued_datain_tasks); 2865 assert(task->current_datain_offset <= task->scsi.transfer_len); 2866 2867 if (task->current_datain_offset == 0) { 2868 task->scsi.lun = spdk_scsi_dev_get_lun(conn->dev, task->scsi.lun_id); 2869 if (task->scsi.lun == NULL) { 2870 TAILQ_REMOVE(&conn->queued_datain_tasks, task, link); 2871 spdk_scsi_task_process_null_lun(&task->scsi); 2872 spdk_iscsi_task_cpl(&task->scsi); 2873 return 0; 2874 } 2875 task->current_datain_offset = task->scsi.length; 2876 conn->data_in_cnt++; 2877 spdk_iscsi_queue_task(conn, task); 2878 continue; 2879 } 2880 if (task->current_datain_offset < task->scsi.transfer_len) { 2881 struct spdk_iscsi_task *subtask; 2882 uint32_t remaining_size = 0; 2883 2884 remaining_size = task->scsi.transfer_len - task->current_datain_offset; 2885 subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl); 2886 assert(subtask != NULL); 2887 subtask->scsi.offset = task->current_datain_offset; 2888 subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size); 2889 spdk_scsi_task_set_data(&subtask->scsi, NULL, 0); 2890 task->current_datain_offset += subtask->scsi.length; 2891 conn->data_in_cnt++; 2892 2893 task->scsi.lun = spdk_scsi_dev_get_lun(conn->dev, task->scsi.lun_id); 2894 if (task->scsi.lun == NULL) { 2895 /* Remove the primary task from the list if this is the last subtask */ 2896 if (task->current_datain_offset == task->scsi.transfer_len) { 2897 TAILQ_REMOVE(&conn->queued_datain_tasks, task, link); 2898 } 2899 subtask->scsi.transfer_len = subtask->scsi.length; 2900 spdk_scsi_task_process_null_lun(&subtask->scsi); 2901 spdk_iscsi_task_cpl(&subtask->scsi); 2902 return 0; 2903 } 2904 2905 spdk_iscsi_queue_task(conn, subtask); 2906 } 2907 if (task->current_datain_offset == task->scsi.transfer_len) { 2908 TAILQ_REMOVE(&conn->queued_datain_tasks, task, link); 2909 } 2910 } 2911 return 0; 2912 } 2913 2914 static int spdk_iscsi_op_scsi_read(struct spdk_iscsi_conn *conn, 2915 struct spdk_iscsi_task *task) 2916 { 2917 int32_t remaining_size = 0; 2918 2919 TAILQ_INIT(&task->subtask_list); 2920 task->scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV; 2921 task->scsi.parent = NULL; 2922 task->scsi.offset = 0; 2923 task->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, task->scsi.transfer_len); 2924 spdk_scsi_task_set_data(&task->scsi, NULL, 0); 2925 2926 remaining_size = task->scsi.transfer_len - task->scsi.length; 2927 task->current_datain_offset = 0; 2928 2929 if (remaining_size == 0) { 2930 spdk_iscsi_queue_task(conn, task); 2931 return 0; 2932 } 2933 2934 TAILQ_INSERT_TAIL(&conn->queued_datain_tasks, task, link); 2935 2936 return spdk_iscsi_conn_handle_queued_tasks(conn); 2937 } 2938 2939 static int 2940 spdk_iscsi_op_scsi(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 2941 { 2942 struct spdk_iscsi_task *task; 2943 struct spdk_scsi_dev *dev; 2944 uint8_t *cdb; 2945 uint64_t lun; 2946 uint32_t task_tag; 2947 uint32_t transfer_len; 2948 int F_bit, R_bit, W_bit; 2949 int lun_i, rc; 2950 struct iscsi_bhs_scsi_req *reqh; 2951 2952 if (conn->sess->session_type != SESSION_TYPE_NORMAL) { 2953 SPDK_ERRLOG("ISCSI_OP_SCSI not allowed in discovery and invalid session\n"); 2954 return SPDK_ISCSI_CONNECTION_FATAL; 2955 } 2956 2957 reqh = (struct iscsi_bhs_scsi_req *)&pdu->bhs; 2958 2959 F_bit = reqh->final_bit; 2960 R_bit = reqh->read_bit; 2961 W_bit = reqh->write_bit; 2962 lun = from_be64(&reqh->lun); 2963 task_tag = from_be32(&reqh->itt); 2964 transfer_len = from_be32(&reqh->expected_data_xfer_len); 2965 cdb = reqh->cdb; 2966 2967 SPDK_TRACEDUMP(SPDK_TRACE_ISCSI, "CDB", cdb, 16); 2968 2969 task = spdk_iscsi_task_get(conn, NULL, spdk_iscsi_task_cpl); 2970 if (!task) { 2971 SPDK_ERRLOG("Unable to acquire task\n"); 2972 return SPDK_ISCSI_CONNECTION_FATAL; 2973 } 2974 2975 spdk_iscsi_task_associate_pdu(task, pdu); 2976 lun_i = spdk_islun2lun(lun); 2977 task->scsi.lun_id = lun_i; 2978 dev = conn->dev; 2979 task->scsi.lun = spdk_scsi_dev_get_lun(dev, lun_i); 2980 2981 if ((R_bit != 0) && (W_bit != 0)) { 2982 SPDK_ERRLOG("Bidirectional CDB is not supported\n"); 2983 spdk_iscsi_task_put(task); 2984 return SPDK_ISCSI_CONNECTION_FATAL; 2985 } 2986 2987 task->scsi.cdb = cdb; 2988 task->tag = task_tag; 2989 task->scsi.transfer_len = transfer_len; 2990 task->scsi.target_port = conn->target_port; 2991 task->scsi.initiator_port = conn->initiator_port; 2992 task->scsi.parent = NULL; 2993 2994 if (task->scsi.lun == NULL) { 2995 spdk_scsi_task_process_null_lun(&task->scsi); 2996 spdk_iscsi_task_cpl(&task->scsi); 2997 return 0; 2998 } 2999 3000 /* no bi-directional support */ 3001 if (R_bit) { 3002 return spdk_iscsi_op_scsi_read(conn, task); 3003 } else if (W_bit) { 3004 task->scsi.dxfer_dir = SPDK_SCSI_DIR_TO_DEV; 3005 3006 if ((conn->sess->ErrorRecoveryLevel >= 1) && 3007 (spdk_iscsi_compare_pdu_bhs_within_existed_r2t_tasks(conn, pdu))) { 3008 spdk_iscsi_task_response(conn, task); 3009 spdk_iscsi_task_put(task); 3010 return 0; 3011 } 3012 3013 if (pdu->data_segment_len > transfer_len) { 3014 SPDK_ERRLOG("data segment len > task transfer len\n"); 3015 spdk_iscsi_task_put(task); 3016 return SPDK_ISCSI_CONNECTION_FATAL; 3017 } 3018 3019 /* check the ImmediateData and also pdu->data_segment_len */ 3020 if ((!conn->sess->ImmediateData && (pdu->data_segment_len > 0)) || 3021 (pdu->data_segment_len > conn->sess->FirstBurstLength)) { 3022 spdk_iscsi_task_put(task); 3023 rc = spdk_iscsi_reject(conn, pdu, 3024 ISCSI_REASON_PROTOCOL_ERROR); 3025 if (rc < 0) { 3026 SPDK_ERRLOG("iscsi_reject() failed\n"); 3027 } 3028 return rc; 3029 } 3030 3031 if (F_bit && pdu->data_segment_len < transfer_len) { 3032 /* needs R2T */ 3033 rc = spdk_add_transfer_task(conn, task); 3034 if (rc < 0) { 3035 SPDK_ERRLOG("add_transfer_task() failed\n"); 3036 spdk_iscsi_task_put(task); 3037 return SPDK_ISCSI_CONNECTION_FATAL; 3038 } 3039 3040 /* Non-immediate writes */ 3041 if (pdu->data_segment_len == 0) 3042 return 0; 3043 else { 3044 /* we are doing the first partial write task */ 3045 task->scsi.ref++; 3046 spdk_scsi_task_set_data(&task->scsi, pdu->data, pdu->data_segment_len); 3047 task->scsi.length = pdu->data_segment_len; 3048 } 3049 } 3050 3051 if (pdu->data_segment_len == transfer_len) { 3052 /* we are doing small writes with no R2T */ 3053 spdk_scsi_task_set_data(&task->scsi, pdu->data, transfer_len); 3054 task->scsi.length = transfer_len; 3055 } 3056 } else { 3057 /* neither R nor W bit set */ 3058 task->scsi.dxfer_dir = SPDK_SCSI_DIR_NONE; 3059 if (transfer_len > 0) { 3060 spdk_iscsi_task_put(task); 3061 SPDK_ERRLOG("Reject scsi cmd with EDTL > 0 but (R | W) == 0\n"); 3062 return spdk_iscsi_reject(conn, pdu, ISCSI_REASON_INVALID_PDU_FIELD); 3063 } 3064 } 3065 3066 spdk_iscsi_queue_task(conn, task); 3067 return 0; 3068 } 3069 3070 void 3071 spdk_iscsi_task_mgmt_response(struct spdk_iscsi_conn *conn, 3072 struct spdk_iscsi_task *task) 3073 { 3074 struct spdk_iscsi_pdu *rsp_pdu; 3075 struct iscsi_bhs_task_req *reqh; 3076 struct iscsi_bhs_task_resp *rsph; 3077 3078 if (task->pdu == NULL) { 3079 /* 3080 * This was an internally generated task management command, 3081 * usually from LUN cleanup when a connection closes. 3082 */ 3083 return; 3084 } 3085 3086 reqh = (struct iscsi_bhs_task_req *)&task->pdu->bhs; 3087 /* response PDU */ 3088 rsp_pdu = spdk_get_pdu(); 3089 rsph = (struct iscsi_bhs_task_resp *)&rsp_pdu->bhs; 3090 rsph->opcode = ISCSI_OP_TASK_RSP; 3091 rsph->flags |= 0x80; /* bit 0 default to 1 */ 3092 switch (task->scsi.response) { 3093 case SPDK_SCSI_TASK_MGMT_RESP_COMPLETE: 3094 rsph->response = ISCSI_TASK_FUNC_RESP_COMPLETE; 3095 break; 3096 case SPDK_SCSI_TASK_MGMT_RESP_SUCCESS: 3097 rsph->response = ISCSI_TASK_FUNC_RESP_COMPLETE; 3098 break; 3099 case SPDK_SCSI_TASK_MGMT_RESP_REJECT: 3100 rsph->response = ISCSI_TASK_FUNC_REJECTED; 3101 break; 3102 case SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN: 3103 rsph->response = ISCSI_TASK_FUNC_RESP_LUN_NOT_EXIST; 3104 break; 3105 case SPDK_SCSI_TASK_MGMT_RESP_TARGET_FAILURE: 3106 rsph->response = ISCSI_TASK_FUNC_REJECTED; 3107 break; 3108 case SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED: 3109 rsph->response = ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED; 3110 break; 3111 } 3112 rsph->itt = reqh->itt; 3113 3114 to_be32(&rsph->stat_sn, conn->StatSN); 3115 conn->StatSN++; 3116 3117 if (reqh->immediate == 0) { 3118 conn->sess->MaxCmdSN++; 3119 } 3120 3121 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 3122 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 3123 3124 spdk_iscsi_write_pdu(conn, rsp_pdu); 3125 } 3126 3127 3128 void spdk_iscsi_task_response(struct spdk_iscsi_conn *conn, 3129 struct spdk_iscsi_task *task) 3130 { 3131 struct spdk_iscsi_pdu *rsp_pdu; 3132 struct iscsi_bhs_scsi_resp *rsph; 3133 uint32_t task_tag; 3134 uint32_t transfer_len; 3135 size_t residual_len; 3136 size_t data_len; 3137 int o_bit, u_bit, O_bit, U_bit; 3138 int bidi_residual_len; 3139 int rc; 3140 struct spdk_iscsi_task *primary; 3141 3142 primary = spdk_iscsi_task_get_primary(task); 3143 3144 transfer_len = primary->scsi.transfer_len; 3145 task_tag = task->tag; 3146 3147 /* transfer data from logical unit */ 3148 /* (direction is view of initiator side) */ 3149 if (spdk_iscsi_task_is_read(primary)) { 3150 rc = spdk_iscsi_transfer_in(conn, task); 3151 if (rc > 0) { 3152 /* sent status by last DATAIN PDU */ 3153 return; 3154 } 3155 3156 if (primary->bytes_completed != primary->scsi.transfer_len) 3157 return; 3158 } 3159 3160 o_bit = u_bit = O_bit = U_bit = 0; 3161 bidi_residual_len = residual_len = 0; 3162 data_len = primary->scsi.data_transferred; 3163 3164 if ((transfer_len != 0) && 3165 (task->scsi.status == SPDK_SCSI_STATUS_GOOD)) { 3166 if (data_len < transfer_len) { 3167 /* underflow */ 3168 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Underflow %zu/%u\n", 3169 data_len, transfer_len); 3170 residual_len = transfer_len - data_len; 3171 U_bit = 1; 3172 } else if (data_len > transfer_len) { 3173 /* overflow */ 3174 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Overflow %zu/%u\n", 3175 data_len, transfer_len); 3176 residual_len = data_len - transfer_len; 3177 O_bit = 1; 3178 } else { 3179 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Transfer %u\n", 3180 transfer_len); 3181 } 3182 } 3183 3184 /* response PDU */ 3185 rsp_pdu = spdk_get_pdu(); 3186 rsph = (struct iscsi_bhs_scsi_resp *)&rsp_pdu->bhs; 3187 assert(task->scsi.sense_data_len <= sizeof(rsp_pdu->sense.data)); 3188 memcpy(rsp_pdu->sense.data, task->scsi.sense_data, task->scsi.sense_data_len); 3189 to_be16(&rsp_pdu->sense.length, task->scsi.sense_data_len); 3190 rsp_pdu->data = (uint8_t *)&rsp_pdu->sense; 3191 rsp_pdu->data_from_mempool = true; 3192 3193 /* 3194 * we need to hold onto this task/cmd because until the 3195 * PDU has been written out 3196 */ 3197 rsp_pdu->task = task; 3198 task->scsi.ref++; 3199 3200 rsph->opcode = ISCSI_OP_SCSI_RSP; 3201 rsph->flags |= 0x80; /* bit 0 is default to 1 */ 3202 3203 if (o_bit) 3204 rsph->flags |= ISCSI_SCSI_BIDI_OVERFLOW; 3205 3206 if (u_bit) 3207 rsph->flags |= ISCSI_SCSI_BIDI_UNDERFLOW; 3208 3209 if (O_bit) 3210 rsph->flags |= ISCSI_SCSI_OVERFLOW; 3211 3212 if (U_bit) 3213 rsph->flags |= ISCSI_SCSI_UNDERFLOW; 3214 3215 rsph->status = task->scsi.status; 3216 if (task->scsi.sense_data_len) { 3217 /* SenseLength (2 bytes) + SenseData */ 3218 DSET24(rsph->data_segment_len, 2 + task->scsi.sense_data_len); 3219 } 3220 to_be32(&rsph->itt, task_tag); 3221 3222 to_be32(&rsph->stat_sn, conn->StatSN); 3223 conn->StatSN++; 3224 3225 if (!spdk_iscsi_task_is_immediate(primary)) 3226 conn->sess->MaxCmdSN++; 3227 3228 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 3229 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 3230 3231 to_be32(&rsph->bi_read_res_cnt, bidi_residual_len); 3232 to_be32(&rsph->res_cnt, residual_len); 3233 3234 spdk_iscsi_write_pdu(conn, rsp_pdu); 3235 } 3236 3237 static struct spdk_iscsi_task * 3238 spdk_get_transfer_task(struct spdk_iscsi_conn *conn, uint32_t transfer_tag) 3239 { 3240 int i; 3241 3242 for (i = 0; i < conn->pending_r2t; i++) { 3243 if (conn->outstanding_r2t_tasks[i]->ttt == transfer_tag) { 3244 return (conn->outstanding_r2t_tasks[i]); 3245 } 3246 } 3247 3248 return NULL; 3249 } 3250 3251 static int 3252 spdk_iscsi_op_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 3253 { 3254 struct iscsi_bhs_task_req *reqh; 3255 uint64_t lun; 3256 uint32_t task_tag; 3257 uint32_t ref_task_tag; 3258 uint8_t function; 3259 int lun_i; 3260 struct spdk_iscsi_task *task; 3261 struct spdk_scsi_dev *dev; 3262 3263 if (conn->sess->session_type != SESSION_TYPE_NORMAL) { 3264 SPDK_ERRLOG("ISCSI_OP_TASK not allowed in discovery and invalid session\n"); 3265 return SPDK_ISCSI_CONNECTION_FATAL; 3266 } 3267 3268 reqh = (struct iscsi_bhs_task_req *)&pdu->bhs; 3269 function = reqh->flags & ISCSI_TASK_FUNCTION_MASK; 3270 lun = from_be64(&reqh->lun); 3271 task_tag = from_be32(&reqh->itt); 3272 ref_task_tag = from_be32(&reqh->ref_task_tag); 3273 3274 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 3275 "I=%d, func=%d, ITT=%x, ref TT=%x, LUN=0x%16.16"PRIx64"\n", 3276 reqh->immediate, function, task_tag, ref_task_tag, lun); 3277 3278 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 3279 "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n", 3280 conn->StatSN, conn->sess->ExpCmdSN, 3281 conn->sess->MaxCmdSN); 3282 3283 lun_i = spdk_islun2lun(lun); 3284 dev = conn->dev; 3285 3286 task = spdk_iscsi_task_get(conn, NULL, spdk_iscsi_task_mgmt_cpl); 3287 if (!task) { 3288 SPDK_ERRLOG("Unable to acquire task\n"); 3289 return SPDK_ISCSI_CONNECTION_FATAL; 3290 } 3291 3292 spdk_iscsi_task_associate_pdu(task, pdu); 3293 task->scsi.target_port = conn->target_port; 3294 task->scsi.initiator_port = conn->initiator_port; 3295 task->tag = task_tag; 3296 task->scsi.lun = spdk_scsi_dev_get_lun(dev, lun_i); 3297 3298 switch (function) { 3299 /* abort task identified by Referenced Task Tag field */ 3300 case ISCSI_TASK_FUNC_ABORT_TASK: 3301 SPDK_NOTICELOG("ABORT_TASK\n"); 3302 3303 task->scsi.abort_id = ref_task_tag; 3304 3305 spdk_iscsi_queue_mgmt_task(conn, task, SPDK_SCSI_TASK_FUNC_ABORT_TASK); 3306 spdk_del_transfer_task(conn, ref_task_tag); 3307 3308 return SPDK_SUCCESS; 3309 3310 /* abort all tasks issued via this session on the LUN */ 3311 case ISCSI_TASK_FUNC_ABORT_TASK_SET: 3312 SPDK_NOTICELOG("ABORT_TASK_SET\n"); 3313 3314 spdk_iscsi_queue_mgmt_task(conn, task, SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET); 3315 spdk_clear_all_transfer_task(conn, task->scsi.lun); 3316 3317 return SPDK_SUCCESS; 3318 3319 case ISCSI_TASK_FUNC_CLEAR_TASK_SET: 3320 task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 3321 SPDK_NOTICELOG("CLEAR_TASK_SET (Unsupported)\n"); 3322 break; 3323 3324 case ISCSI_TASK_FUNC_CLEAR_ACA: 3325 task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 3326 SPDK_NOTICELOG("CLEAR_ACA (Unsupported)\n"); 3327 break; 3328 3329 case ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET: 3330 SPDK_NOTICELOG("LOGICAL_UNIT_RESET\n"); 3331 3332 spdk_iscsi_queue_mgmt_task(conn, task, SPDK_SCSI_TASK_FUNC_LUN_RESET); 3333 spdk_clear_all_transfer_task(conn, task->scsi.lun); 3334 return SPDK_SUCCESS; 3335 3336 case ISCSI_TASK_FUNC_TARGET_WARM_RESET: 3337 SPDK_NOTICELOG("TARGET_WARM_RESET (Unsupported)\n"); 3338 3339 #if 0 3340 spdk_iscsi_drop_conns(conn, conn->initiator_name, 1 /* drop all */); 3341 rc = spdk_iscsi_tgt_node_reset(conn->sess->target, lun); 3342 if (rc < 0) 3343 SPDK_ERRLOG("tgt_node reset failed\n"); 3344 #else 3345 task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 3346 #endif 3347 break; 3348 3349 case ISCSI_TASK_FUNC_TARGET_COLD_RESET: 3350 SPDK_NOTICELOG("TARGET_COLD_RESET\n"); 3351 3352 #if 0 3353 spdk_iscsi_drop_conns(conn, conn->initiator_name, 1 /* drop all */); 3354 3355 rc = spdk_iscsi_tgt_node_reset(conn->sess->target, lun); 3356 if (rc < 0) 3357 SPDK_ERRLOG("tgt_node reset failed\n"); 3358 3359 conn->state = ISCSI_CONN_STATE_EXITING; 3360 #else 3361 task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 3362 #endif 3363 break; 3364 3365 case ISCSI_TASK_FUNC_TASK_REASSIGN: 3366 SPDK_NOTICELOG("TASK_REASSIGN (Unsupported)\n"); 3367 task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED; 3368 break; 3369 3370 default: 3371 SPDK_ERRLOG("unsupported function %d\n", function); 3372 task->scsi.response = SPDK_SCSI_TASK_MGMT_RESP_REJECT; 3373 break; 3374 } 3375 3376 spdk_iscsi_task_mgmt_response(conn, task); 3377 spdk_iscsi_task_put(task); 3378 return 0; 3379 } 3380 3381 static int 3382 spdk_iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 3383 { 3384 struct spdk_iscsi_pdu *rsp_pdu; 3385 struct iscsi_bhs_nop_out *reqh; 3386 struct iscsi_bhs_nop_in *rsph; 3387 uint8_t *data; 3388 uint64_t lun; 3389 uint32_t task_tag; 3390 uint32_t transfer_tag; 3391 uint32_t CmdSN; 3392 int I_bit; 3393 int data_len; 3394 3395 if (conn->sess->session_type == SESSION_TYPE_DISCOVERY) { 3396 SPDK_ERRLOG("ISCSI_OP_NOPOUT not allowed in discovery session\n"); 3397 return SPDK_ISCSI_CONNECTION_FATAL; 3398 } 3399 3400 reqh = (struct iscsi_bhs_nop_out *)&pdu->bhs; 3401 I_bit = reqh->immediate; 3402 3403 data_len = DGET24(reqh->data_segment_len); 3404 if (data_len > conn->MaxRecvDataSegmentLength) { 3405 data_len = conn->MaxRecvDataSegmentLength; 3406 } 3407 3408 lun = from_be64(&reqh->lun); 3409 task_tag = from_be32(&reqh->itt); 3410 transfer_tag = from_be32(&reqh->ttt); 3411 CmdSN = from_be32(&reqh->cmd_sn); 3412 pdu->cmd_sn = CmdSN; 3413 3414 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "I=%d, ITT=%x, TTT=%x\n", 3415 I_bit, task_tag, transfer_tag); 3416 3417 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 3418 "CmdSN=%u, StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n", 3419 CmdSN, conn->StatSN, conn->sess->ExpCmdSN, 3420 conn->sess->MaxCmdSN); 3421 3422 if (transfer_tag != 0xFFFFFFFF && transfer_tag != (uint32_t)conn->id) { 3423 SPDK_ERRLOG("invalid transfer tag 0x%x\n", transfer_tag); 3424 /* 3425 * Technically we should probably fail the connection here, but for now 3426 * just print the error message and continue. 3427 */ 3428 } 3429 3430 /* 3431 * We don't actually check to see if this is a response to the NOP-In 3432 * that we sent. Our goal is to just verify that the initiator is 3433 * alive and responding to commands, not to verify that it tags 3434 * NOP-Outs correctly 3435 */ 3436 conn->nop_outstanding = false; 3437 3438 if (task_tag == 0xffffffffU) { 3439 if (I_bit == 1) { 3440 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 3441 "got NOPOUT ITT=0xffffffff\n"); 3442 return SPDK_SUCCESS; 3443 } else { 3444 SPDK_ERRLOG("got NOPOUT ITT=0xffffffff, I=0\n"); 3445 return SPDK_ISCSI_CONNECTION_FATAL; 3446 } 3447 } 3448 3449 data = malloc(data_len); 3450 if (!data) { 3451 perror("could not allocate ping buffer"); 3452 return SPDK_ISCSI_CONNECTION_FATAL; 3453 } 3454 memset(data, 0, data_len); 3455 3456 /* response of NOPOUT */ 3457 if (data_len > 0) { 3458 /* copy ping data */ 3459 memcpy(data, pdu->data, data_len); 3460 } 3461 3462 transfer_tag = 0xffffffffU; 3463 3464 /* response PDU */ 3465 rsp_pdu = spdk_get_pdu(); 3466 rsph = (struct iscsi_bhs_nop_in *)&rsp_pdu->bhs; 3467 rsp_pdu->data = data; 3468 rsph->opcode = ISCSI_OP_NOPIN; 3469 rsph->flags |= 0x80; /* bit 0 default to 1 */ 3470 DSET24(rsph->data_segment_len, data_len); 3471 to_be64(&rsph->lun, lun); 3472 to_be32(&rsph->itt, task_tag); 3473 to_be32(&rsph->ttt, transfer_tag); 3474 3475 to_be32(&rsph->stat_sn, conn->StatSN); 3476 conn->StatSN++; 3477 3478 if (I_bit == 0) { 3479 conn->sess->MaxCmdSN++; 3480 } 3481 3482 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 3483 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 3484 3485 spdk_iscsi_write_pdu(conn, rsp_pdu); 3486 conn->last_nopin = spdk_get_ticks(); 3487 3488 return SPDK_SUCCESS; 3489 } 3490 3491 static int 3492 spdk_add_transfer_task(struct spdk_iscsi_conn *conn, 3493 struct spdk_iscsi_task *task) 3494 { 3495 uint32_t transfer_len; 3496 size_t max_burst_len; 3497 size_t segment_len; 3498 size_t data_len; 3499 int len; 3500 int idx; 3501 int rc; 3502 int data_out_req; 3503 3504 transfer_len = task->scsi.transfer_len; 3505 data_len = spdk_iscsi_task_get_pdu(task)->data_segment_len; 3506 max_burst_len = conn->sess->MaxBurstLength; 3507 segment_len = g_spdk_iscsi.MaxRecvDataSegmentLength; 3508 data_out_req = 1 + (transfer_len - data_len - 1) / segment_len; 3509 task->data_out_cnt = data_out_req; 3510 3511 /* 3512 * If we already have too many tasks using R2T, then queue this task 3513 * and start sending R2T for it after some of the tasks using R2T/data 3514 * out buffers complete. 3515 */ 3516 if (conn->pending_r2t >= DEFAULT_MAXR2T) { 3517 TAILQ_INSERT_TAIL(&conn->queued_r2t_tasks, task, link); 3518 return SPDK_SUCCESS; 3519 } 3520 3521 conn->data_out_cnt += data_out_req; 3522 idx = conn->pending_r2t++; 3523 3524 conn->outstanding_r2t_tasks[idx] = task; 3525 task->next_expected_r2t_offset = data_len; 3526 task->current_r2t_length = 0; 3527 task->R2TSN = 0; 3528 task->ttt = ++conn->ttt; 3529 3530 while (data_len != transfer_len) { 3531 len = DMIN32(max_burst_len, (transfer_len - data_len)); 3532 rc = spdk_iscsi_send_r2t(conn, task, data_len, len, 3533 task->ttt, &task->R2TSN); 3534 if (rc < 0) { 3535 SPDK_ERRLOG("iscsi_send_r2t() failed\n"); 3536 return rc; 3537 } 3538 data_len += len; 3539 task->next_r2t_offset = data_len; 3540 task->outstanding_r2t++; 3541 if (conn->sess->MaxOutstandingR2T == task->outstanding_r2t) 3542 break; 3543 } 3544 3545 TAILQ_INSERT_TAIL(&conn->active_r2t_tasks, task, link); 3546 return SPDK_SUCCESS; 3547 } 3548 3549 void spdk_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t task_tag) 3550 { 3551 struct spdk_iscsi_task *task; 3552 int found = 0; 3553 int i; 3554 3555 for (i = 0; i < conn->pending_r2t; i++) { 3556 if (conn->outstanding_r2t_tasks[i]->tag == task_tag) { 3557 task = conn->outstanding_r2t_tasks[i]; 3558 conn->outstanding_r2t_tasks[i] = NULL; 3559 conn->data_out_cnt -= task->data_out_cnt; 3560 found = 1; 3561 break; 3562 } 3563 } 3564 3565 if (found) { 3566 for (; i < conn->pending_r2t - 1; i++) 3567 conn->outstanding_r2t_tasks[i] = conn->outstanding_r2t_tasks[i + 1]; 3568 3569 conn->pending_r2t--; 3570 conn->outstanding_r2t_tasks[conn->pending_r2t] = NULL; 3571 } 3572 3573 /* 3574 * A large write was just completed, so if there are additional large 3575 * writes queued for R2Ts, start them now. But first check to make 3576 * sure each of the tasks will fit without the connection's allotment 3577 * for total R2T tasks. 3578 */ 3579 while (!TAILQ_EMPTY(&conn->queued_r2t_tasks)) { 3580 task = TAILQ_FIRST(&conn->queued_r2t_tasks); 3581 if (conn->pending_r2t < DEFAULT_MAXR2T) { 3582 TAILQ_REMOVE(&conn->queued_r2t_tasks, task, link); 3583 spdk_add_transfer_task(conn, task); 3584 } else { 3585 break; 3586 } 3587 } 3588 } 3589 3590 void spdk_del_connection_queued_task(void *tailq, struct spdk_scsi_lun *lun) 3591 { 3592 struct spdk_iscsi_task *task, *task_tmp; 3593 /* 3594 * Temporary used to index spdk_scsi_task related 3595 * queues of the connection. 3596 */ 3597 TAILQ_HEAD(queued_tasks, spdk_iscsi_task) *head; 3598 head = (struct queued_tasks *)tailq; 3599 3600 TAILQ_FOREACH_SAFE(task, head, link, task_tmp) { 3601 if (lun == NULL || lun == task->scsi.lun) { 3602 TAILQ_REMOVE(head, task, link); 3603 spdk_iscsi_task_put(task); 3604 } 3605 } 3606 } 3607 3608 void spdk_clear_all_transfer_task(struct spdk_iscsi_conn *conn, 3609 struct spdk_scsi_lun *lun) 3610 { 3611 int i, j, pending_r2t; 3612 struct spdk_iscsi_task *task; 3613 3614 pending_r2t = conn->pending_r2t; 3615 for (i = 0; i < pending_r2t; i++) { 3616 task = conn->outstanding_r2t_tasks[i]; 3617 if (lun == NULL || lun == task->scsi.lun) { 3618 conn->outstanding_r2t_tasks[i] = NULL; 3619 task->outstanding_r2t = 0; 3620 task->next_r2t_offset = 0; 3621 task->next_expected_r2t_offset = 0; 3622 conn->data_out_cnt -= task->data_out_cnt; 3623 conn->pending_r2t--; 3624 } 3625 } 3626 3627 for (i = 0; i < pending_r2t; i++) { 3628 if (conn->outstanding_r2t_tasks[i] != NULL) 3629 continue; 3630 for (j = i + 1; j < pending_r2t; j++) { 3631 if (conn->outstanding_r2t_tasks[j] != NULL) { 3632 conn->outstanding_r2t_tasks[i] = conn->outstanding_r2t_tasks[j]; 3633 conn->outstanding_r2t_tasks[j] = NULL; 3634 break; 3635 } 3636 } 3637 } 3638 3639 spdk_del_connection_queued_task(&conn->active_r2t_tasks, lun); 3640 spdk_del_connection_queued_task(&conn->queued_r2t_tasks, lun); 3641 } 3642 3643 /* This function is used to handle the r2t snack */ 3644 static int 3645 spdk_iscsi_handle_r2t_snack(struct spdk_iscsi_conn *conn, 3646 struct spdk_iscsi_task *task, 3647 struct spdk_iscsi_pdu *pdu, uint32_t beg_run, 3648 uint32_t run_length, int32_t task_tag) 3649 { 3650 int32_t last_r2tsn; 3651 int i; 3652 3653 if (beg_run < task->acked_r2tsn) { 3654 SPDK_ERRLOG("ITT: 0x%08x, R2T SNACK requests retransmission of" 3655 "R2TSN: from 0x%08x to 0x%08x. But it has already" 3656 "ack to R2TSN:0x%08x, protocol error.\n", 3657 task_tag, beg_run, (beg_run + run_length), 3658 (task->acked_r2tsn - 1)); 3659 return spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 3660 } 3661 3662 if (run_length) { 3663 if ((beg_run + run_length) > task->R2TSN) { 3664 SPDK_ERRLOG("ITT: 0x%08x, received R2T SNACK with" 3665 "BegRun: 0x%08x, RunLength: 0x%08x, exceeds" 3666 "current R2TSN: 0x%08x, protocol error.\n", 3667 task_tag, beg_run, run_length, 3668 task->R2TSN); 3669 3670 return spdk_iscsi_reject(conn, pdu, 3671 ISCSI_REASON_INVALID_PDU_FIELD); 3672 } 3673 last_r2tsn = (beg_run + run_length); 3674 } else 3675 last_r2tsn = task->R2TSN; 3676 3677 for (i = beg_run; i < last_r2tsn; i++) 3678 if (spdk_iscsi_send_r2t_recovery(conn, task, i, false) < 0) 3679 SPDK_ERRLOG("The r2t_sn=%d of r2t_task=%p is " 3680 "not sent\n", i, task); 3681 3682 return 0; 3683 } 3684 3685 /* This function is used to recover the data in packet */ 3686 static int 3687 spdk_iscsi_handle_recovery_datain(struct spdk_iscsi_conn *conn, 3688 struct spdk_iscsi_task *task, 3689 struct spdk_iscsi_pdu *pdu, uint32_t beg_run, 3690 uint32_t run_length, uint32_t task_tag) 3691 { 3692 struct spdk_iscsi_pdu *old_pdu, *pdu_temp; 3693 uint32_t i; 3694 struct iscsi_bhs_data_in *datain_header; 3695 uint32_t last_statsn; 3696 3697 task = spdk_iscsi_task_get_primary(task); 3698 3699 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "spdk_iscsi_handle_recovery_datain\n"); 3700 3701 if (beg_run < task->acked_data_sn) { 3702 SPDK_ERRLOG("ITT: 0x%08x, DATA IN SNACK requests retransmission of" 3703 "DATASN: from 0x%08x to 0x%08x but already acked to " 3704 "DATASN: 0x%08x protocol error\n", 3705 task_tag, beg_run, 3706 (beg_run + run_length), (task->acked_data_sn - 1)); 3707 3708 return spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 3709 } 3710 3711 if (run_length == 0) 3712 /* as the DataSN begins at 0 */ 3713 run_length = task->datain_datasn + 1; 3714 3715 if ((beg_run + run_length - 1) > task->datain_datasn) { 3716 SPDK_ERRLOG("Initiator requests BegRun: 0x%08x, RunLength:" 3717 "0x%08x greater than maximum DataSN: 0x%08x.\n", 3718 beg_run, run_length, task->datain_datasn); 3719 3720 return -1; 3721 } else 3722 last_statsn = beg_run + run_length - 1; 3723 3724 for (i = beg_run; i <= last_statsn; i++) { 3725 TAILQ_FOREACH_SAFE(old_pdu, &conn->snack_pdu_list, tailq, pdu_temp) { 3726 if (old_pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) { 3727 datain_header = (struct iscsi_bhs_data_in *)&old_pdu->bhs; 3728 if (from_be32(&datain_header->itt) == task_tag && 3729 from_be32(&datain_header->data_sn) == i) { 3730 TAILQ_REMOVE(&conn->snack_pdu_list, old_pdu, tailq); 3731 spdk_iscsi_write_pdu(conn, old_pdu); 3732 break; 3733 } 3734 } 3735 } 3736 } 3737 return 0; 3738 } 3739 3740 /* This function is used to handle the status snack */ 3741 static int 3742 spdk_iscsi_handle_status_snack(struct spdk_iscsi_conn *conn, 3743 struct spdk_iscsi_pdu *pdu) 3744 { 3745 uint32_t beg_run; 3746 uint32_t run_length; 3747 struct iscsi_bhs_snack_req *reqh; 3748 uint32_t i; 3749 uint32_t last_statsn; 3750 bool found_pdu; 3751 struct spdk_iscsi_pdu *old_pdu; 3752 3753 reqh = (struct iscsi_bhs_snack_req *)&pdu->bhs; 3754 beg_run = from_be32(&reqh->beg_run); 3755 run_length = from_be32(&reqh->run_len); 3756 3757 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "beg_run=%d, run_length=%d, conn->StatSN=" 3758 "%d, conn->exp_statsn=%d\n", beg_run, run_length, 3759 conn->StatSN, conn->exp_statsn); 3760 3761 if (!beg_run) 3762 beg_run = conn->exp_statsn; 3763 else if (beg_run < conn->exp_statsn) { 3764 SPDK_ERRLOG("Got Status SNACK Begrun: 0x%08x, RunLength: 0x%08x " 3765 "but already got ExpStatSN: 0x%08x on CID:%hu.\n", 3766 beg_run, run_length, conn->StatSN, conn->cid); 3767 3768 spdk_iscsi_reject(conn, pdu, ISCSI_REASON_INVALID_PDU_FIELD); 3769 return 0; 3770 } 3771 3772 last_statsn = (!run_length) ? conn->StatSN : (beg_run + run_length); 3773 3774 for (i = beg_run; i < last_statsn; i++) { 3775 found_pdu = false; 3776 TAILQ_FOREACH(old_pdu, &conn->snack_pdu_list, tailq) { 3777 if (from_be32(&old_pdu->bhs.stat_sn) == i) { 3778 found_pdu = true; 3779 break; 3780 } 3781 } 3782 3783 if (!found_pdu) { 3784 SPDK_ERRLOG("Unable to find StatSN: 0x%08x. For a Status" 3785 "SNACK, assuming this is a proactive SNACK " 3786 "for an untransmitted StatSN, ignoring.\n", 3787 beg_run); 3788 } else { 3789 TAILQ_REMOVE(&conn->snack_pdu_list, old_pdu, tailq); 3790 spdk_iscsi_write_pdu(conn, old_pdu); 3791 } 3792 } 3793 3794 return 0; 3795 } 3796 3797 /* This function is used to handle the data ack snack */ 3798 static int 3799 spdk_iscsi_handle_data_ack(struct spdk_iscsi_conn *conn, 3800 struct spdk_iscsi_pdu *pdu) 3801 { 3802 uint32_t transfer_tag; 3803 uint32_t beg_run; 3804 uint32_t run_length; 3805 struct spdk_iscsi_pdu *old_pdu; 3806 uint32_t old_datasn; 3807 int rc; 3808 struct iscsi_bhs_snack_req *reqh; 3809 struct spdk_iscsi_task *task; 3810 struct iscsi_bhs_data_in *datain_header; 3811 struct spdk_iscsi_task *primary; 3812 3813 reqh = (struct iscsi_bhs_snack_req *)&pdu->bhs; 3814 transfer_tag = from_be32(&reqh->ttt); 3815 beg_run = from_be32(&reqh->beg_run); 3816 run_length = from_be32(&reqh->run_len); 3817 task = NULL; 3818 datain_header = NULL; 3819 3820 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "beg_run=%d,transfer_tag=%d,run_len=%d\n", 3821 beg_run, transfer_tag, run_length); 3822 3823 task = spdk_get_scsi_task_from_ttt(conn, transfer_tag); 3824 if (!task) { 3825 SPDK_ERRLOG("Data ACK SNACK for TTT: 0x%08x is invalid.\n", 3826 transfer_tag); 3827 goto reject_return; 3828 } 3829 3830 primary = spdk_iscsi_task_get_primary(task); 3831 if ((run_length != 0) || (beg_run < primary->acked_data_sn)) { 3832 SPDK_ERRLOG("TTT: 0x%08x Data ACK SNACK BegRUN: %d is less than " 3833 "the next expected acked DataSN: %d\n", 3834 transfer_tag, beg_run, primary->acked_data_sn); 3835 goto reject_return; 3836 } 3837 3838 primary->acked_data_sn = beg_run; 3839 3840 /* To free the pdu */ 3841 TAILQ_FOREACH(old_pdu, &conn->snack_pdu_list, tailq) { 3842 if (old_pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) { 3843 datain_header = (struct iscsi_bhs_data_in *) &old_pdu->bhs; 3844 old_datasn = from_be32(&datain_header->data_sn); 3845 if ((from_be32(&datain_header->ttt) == transfer_tag) && 3846 (old_datasn == beg_run - 1)) { 3847 TAILQ_REMOVE(&conn->snack_pdu_list, old_pdu, tailq); 3848 if (old_pdu->task) 3849 spdk_iscsi_task_put(old_pdu->task); 3850 spdk_put_pdu(old_pdu); 3851 break; 3852 } 3853 } 3854 } 3855 3856 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Received Data ACK SNACK for TTT: 0x%08x," 3857 " updated acked DataSN to 0x%08x.\n", transfer_tag, 3858 (task->acked_data_sn - 1)); 3859 3860 return 0; 3861 3862 reject_return: 3863 rc = spdk_iscsi_reject(conn, pdu, ISCSI_REASON_INVALID_SNACK); 3864 if (rc < 0) { 3865 SPDK_ERRLOG("iscsi_reject() failed\n"); 3866 return -1; 3867 } 3868 3869 return 0; 3870 } 3871 3872 /* This function is used to remove the r2t pdu from snack_pdu_list by < task, r2t_sn> info */ 3873 static struct spdk_iscsi_pdu * 3874 spdk_iscsi_remove_r2t_pdu_from_snack_list(struct spdk_iscsi_conn *conn, 3875 struct spdk_iscsi_task *task, 3876 uint32_t r2t_sn) 3877 { 3878 struct spdk_iscsi_pdu *pdu = NULL; 3879 struct iscsi_bhs_r2t *r2t_header; 3880 bool found_pdu = false; 3881 3882 TAILQ_FOREACH(pdu, &conn->snack_pdu_list, tailq) { 3883 if (pdu->bhs.opcode == ISCSI_OP_R2T) { 3884 r2t_header = (struct iscsi_bhs_r2t *)&pdu->bhs; 3885 if (pdu->task == task && 3886 from_be32(&r2t_header->r2t_sn) == r2t_sn) { 3887 found_pdu = true; 3888 break; 3889 } 3890 } 3891 } 3892 3893 if (found_pdu) 3894 TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq); 3895 else 3896 pdu = NULL; 3897 3898 return pdu; 3899 3900 } 3901 3902 /* This function is used re-send the r2t packet */ 3903 static int 3904 spdk_iscsi_send_r2t_recovery(struct spdk_iscsi_conn *conn, 3905 struct spdk_iscsi_task *task, uint32_t r2t_sn, 3906 bool send_new_r2tsn) 3907 { 3908 struct spdk_iscsi_pdu *pdu; 3909 struct iscsi_bhs_r2t *rsph; 3910 uint32_t transfer_len; 3911 uint32_t len; 3912 3913 /* remove the r2t pdu from the snack_list */ 3914 pdu = spdk_iscsi_remove_r2t_pdu_from_snack_list(conn, task, r2t_sn); 3915 if (!pdu) { 3916 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "No pdu is found\n"); 3917 return -1; 3918 } 3919 3920 /* flag 3921 * false: only need to re-send the old r2t with changing statsn 3922 * true: we send a r2t with new r2tsn 3923 */ 3924 if (!send_new_r2tsn) { 3925 to_be32(&pdu->bhs.stat_sn, conn->StatSN); 3926 spdk_iscsi_write_pdu(conn, pdu); 3927 } else { 3928 rsph = (struct iscsi_bhs_r2t *)&pdu->bhs; 3929 transfer_len = from_be32(&rsph->desired_xfer_len); 3930 3931 /* still need to increase the acked r2tsn */ 3932 task->acked_r2tsn++; 3933 len = DMIN32(conn->sess->MaxBurstLength, (transfer_len - 3934 task->next_expected_r2t_offset)); 3935 3936 /* remove the old_r2t_pdu */ 3937 if (pdu->task) 3938 spdk_iscsi_task_put(pdu->task); 3939 spdk_put_pdu(pdu); 3940 3941 /* re-send a new r2t pdu */ 3942 spdk_iscsi_send_r2t(conn, task, task->next_expected_r2t_offset, 3943 len, task->ttt, &task->R2TSN); 3944 } 3945 3946 return 0; 3947 } 3948 3949 /* This function is used to handle the snack request from the initiator */ 3950 static int 3951 spdk_iscsi_op_snack(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 3952 { 3953 struct iscsi_bhs_snack_req *reqh; 3954 struct spdk_iscsi_task *task; 3955 int type; 3956 uint32_t task_tag; 3957 uint32_t beg_run; 3958 uint32_t run_length; 3959 int rc; 3960 3961 if (conn->sess->session_type == SESSION_TYPE_DISCOVERY) { 3962 SPDK_ERRLOG("ISCSI_OP_SNACK not allowed in discovery session\n"); 3963 return SPDK_ISCSI_CONNECTION_FATAL; 3964 } 3965 3966 reqh = (struct iscsi_bhs_snack_req *)&pdu->bhs; 3967 if (!conn->sess->ErrorRecoveryLevel) { 3968 SPDK_ERRLOG("Got a SNACK request in ErrorRecoveryLevel=0\n"); 3969 rc = spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 3970 if (rc < 0) { 3971 SPDK_ERRLOG("iscsi_reject() failed\n"); 3972 return -1; 3973 } 3974 return rc; 3975 } 3976 3977 type = reqh->flags & ISCSI_FLAG_SNACK_TYPE_MASK; 3978 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "The value of type is %d\n", type); 3979 3980 switch (type) { 3981 case 0: 3982 reqh = (struct iscsi_bhs_snack_req *)&pdu->bhs; 3983 task_tag = from_be32(&reqh->itt); 3984 beg_run = from_be32(&reqh->beg_run); 3985 run_length = from_be32(&reqh->run_len); 3986 3987 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "beg_run=%d, run_length=%d, " 3988 "task_tag=%x, transfer_tag=%u\n", beg_run, 3989 run_length, task_tag, from_be32(&reqh->ttt)); 3990 3991 task = spdk_get_scsi_task_from_itt(conn, task_tag, 3992 ISCSI_OP_SCSI_DATAIN); 3993 if (task) 3994 return spdk_iscsi_handle_recovery_datain(conn, task, pdu, 3995 beg_run, 3996 run_length, 3997 task_tag); 3998 3999 task = spdk_get_scsi_task_from_itt(conn, task_tag, ISCSI_OP_R2T); 4000 if (task) 4001 return spdk_iscsi_handle_r2t_snack(conn, task, pdu, 4002 beg_run, run_length, 4003 task_tag); 4004 4005 SPDK_ERRLOG("It is Neither datain nor r2t recovery request\n"); 4006 rc = -1; 4007 break; 4008 case ISCSI_FLAG_SNACK_TYPE_STATUS: 4009 rc = spdk_iscsi_handle_status_snack(conn, pdu); 4010 break; 4011 case ISCSI_FLAG_SNACK_TYPE_DATA_ACK: 4012 rc = spdk_iscsi_handle_data_ack(conn, pdu); 4013 break; 4014 case ISCSI_FLAG_SNACK_TYPE_RDATA: 4015 SPDK_ERRLOG("R-Data SNACK is Not Supported int spdk\n"); 4016 rc = spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 4017 break; 4018 default: 4019 SPDK_ERRLOG("Unknown SNACK type %d, protocol error\n", type); 4020 rc = spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 4021 break; 4022 } 4023 4024 return rc; 4025 } 4026 4027 /* This fucntion is used to refree the pdu when it is acknowledged */ 4028 static void 4029 spdk_remove_acked_pdu(struct spdk_iscsi_conn *conn, 4030 uint32_t ExpStatSN) 4031 { 4032 struct spdk_iscsi_pdu *pdu, *pdu_temp; 4033 uint32_t stat_sn; 4034 4035 conn->exp_statsn = DMIN32(ExpStatSN, conn->StatSN); 4036 TAILQ_FOREACH_SAFE(pdu, &conn->snack_pdu_list, tailq, pdu_temp) { 4037 stat_sn = from_be32(&pdu->bhs.stat_sn); 4038 if (SN32_LT(stat_sn, conn->exp_statsn)) { 4039 TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq); 4040 spdk_iscsi_conn_free_pdu(conn, pdu); 4041 } 4042 } 4043 } 4044 4045 static int spdk_iscsi_op_data(struct spdk_iscsi_conn *conn, 4046 struct spdk_iscsi_pdu *pdu) 4047 { 4048 struct spdk_iscsi_task *task, *subtask; 4049 struct iscsi_bhs_data_out *reqh; 4050 struct spdk_scsi_lun *lun_dev; 4051 uint32_t transfer_tag; 4052 uint32_t task_tag; 4053 uint32_t transfer_len; 4054 uint32_t DataSN; 4055 uint32_t buffer_offset; 4056 uint32_t len; 4057 uint64_t lun; 4058 int lun_i; 4059 int F_bit; 4060 int rc; 4061 4062 if (conn->sess->session_type == SESSION_TYPE_DISCOVERY) { 4063 SPDK_ERRLOG("ISCSI_OP_SCSI_DATAOUT not allowed in discovery session\n"); 4064 return SPDK_ISCSI_CONNECTION_FATAL; 4065 } 4066 4067 reqh = (struct iscsi_bhs_data_out *)&pdu->bhs; 4068 F_bit = !!(reqh->flags & ISCSI_FLAG_FINAL); 4069 transfer_tag = from_be32(&reqh->ttt); 4070 task_tag = from_be32(&reqh->itt); 4071 DataSN = from_be32(&reqh->data_sn); 4072 buffer_offset = from_be32(&reqh->buffer_offset); 4073 lun = from_be64(&reqh->lun); 4074 lun_i = spdk_islun2lun(lun); 4075 lun_dev = spdk_scsi_dev_get_lun(conn->dev, lun_i); 4076 4077 task = spdk_get_transfer_task(conn, transfer_tag); 4078 if (task == NULL) { 4079 SPDK_ERRLOG("Not found task for transfer_tag=%x\n", transfer_tag); 4080 goto reject_return; 4081 } 4082 4083 if (pdu->data_segment_len > task->desired_data_transfer_length) { 4084 SPDK_ERRLOG("the dataout pdu data length is larger than the value sent by R2T PDU\n"); 4085 return SPDK_ISCSI_CONNECTION_FATAL; 4086 } 4087 4088 if (task->tag != task_tag) { 4089 SPDK_ERRLOG("The r2t task tag is %u, and the dataout task tag is %u\n", 4090 task->tag, task_tag); 4091 goto reject_return; 4092 } 4093 4094 if (DataSN != task->r2t_datasn) { 4095 SPDK_ERRLOG("DataSN(%u) exp=%d error\n", DataSN, task->r2t_datasn); 4096 if (conn->sess->ErrorRecoveryLevel >= 1) { 4097 goto send_r2t_recovery_return; 4098 } else { 4099 return SPDK_ISCSI_CONNECTION_FATAL; 4100 } 4101 } 4102 4103 if (buffer_offset != task->next_expected_r2t_offset) { 4104 SPDK_ERRLOG("offset(%u) error\n", buffer_offset); 4105 return SPDK_ISCSI_CONNECTION_FATAL; 4106 } 4107 4108 transfer_len = task->scsi.transfer_len; 4109 task->current_r2t_length += pdu->data_segment_len; 4110 task->next_expected_r2t_offset += pdu->data_segment_len; 4111 task->r2t_datasn++; 4112 4113 if (task->current_r2t_length > conn->sess->MaxBurstLength) { 4114 SPDK_ERRLOG("R2T burst(%u) > MaxBurstLength(%u)\n", 4115 task->current_r2t_length, 4116 conn->sess->MaxBurstLength); 4117 return SPDK_ISCSI_CONNECTION_FATAL; 4118 } 4119 4120 if (F_bit) { 4121 /* 4122 * This R2T burst is done. Clear the length before we 4123 * receive a PDU for the next R2T burst. 4124 */ 4125 task->current_r2t_length = 0; 4126 } 4127 4128 subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl); 4129 if (subtask == NULL) { 4130 SPDK_ERRLOG("Unable to acquire subtask\n"); 4131 return SPDK_ISCSI_CONNECTION_FATAL; 4132 } 4133 subtask->scsi.offset = buffer_offset; 4134 subtask->scsi.length = pdu->data_segment_len; 4135 spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_segment_len); 4136 spdk_iscsi_task_associate_pdu(subtask, pdu); 4137 4138 if (task->next_expected_r2t_offset == transfer_len) { 4139 task->acked_r2tsn++; 4140 } else if (F_bit && (task->next_r2t_offset < transfer_len)) { 4141 task->acked_r2tsn++; 4142 len = DMIN32(conn->sess->MaxBurstLength, (transfer_len - 4143 task->next_r2t_offset)); 4144 rc = spdk_iscsi_send_r2t(conn, task, 4145 task->next_r2t_offset, len, 4146 task->ttt, &task->R2TSN); 4147 if (rc < 0) { 4148 SPDK_ERRLOG("iscsi_send_r2t() failed\n"); 4149 } 4150 task->next_r2t_offset += len; 4151 } 4152 4153 if (lun_dev == NULL) { 4154 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "LUN %d is removed, complete the task immediately\n", lun_i); 4155 subtask->scsi.transfer_len = subtask->scsi.length; 4156 spdk_scsi_task_process_null_lun(&subtask->scsi); 4157 spdk_iscsi_task_cpl(&subtask->scsi); 4158 return 0; 4159 } 4160 4161 spdk_iscsi_queue_task(conn, subtask); 4162 return 0; 4163 4164 send_r2t_recovery_return: 4165 rc = spdk_iscsi_send_r2t_recovery(conn, task, task->acked_r2tsn, true); 4166 if (rc < 0) 4167 goto reject_return; 4168 return rc; 4169 4170 reject_return: 4171 rc = spdk_iscsi_reject(conn, pdu, ISCSI_REASON_INVALID_PDU_FIELD); 4172 if (rc < 0) { 4173 SPDK_ERRLOG("iscsi_reject() failed\n"); 4174 return SPDK_ISCSI_CONNECTION_FATAL; 4175 } 4176 4177 return SPDK_SUCCESS; 4178 } 4179 4180 static int 4181 spdk_iscsi_send_r2t(struct spdk_iscsi_conn *conn, 4182 struct spdk_iscsi_task *task, int offset, 4183 int len, uint32_t transfer_tag, uint32_t *R2TSN) 4184 { 4185 struct spdk_iscsi_pdu *rsp_pdu; 4186 struct iscsi_bhs_r2t *rsph; 4187 4188 /* R2T PDU */ 4189 rsp_pdu = spdk_get_pdu(); 4190 rsph = (struct iscsi_bhs_r2t *)&rsp_pdu->bhs; 4191 rsp_pdu->data = NULL; 4192 rsph->opcode = ISCSI_OP_R2T; 4193 rsph->flags |= 0x80; /* bit 0 is default to 1 */ 4194 to_be64(&rsph->lun, spdk_scsi_lun_get_id(task->scsi.lun)); 4195 to_be32(&rsph->itt, task->tag); 4196 to_be32(&rsph->ttt, transfer_tag); 4197 4198 to_be32(&rsph->stat_sn, conn->StatSN); 4199 to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN); 4200 to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN); 4201 4202 to_be32(&rsph->r2t_sn, *R2TSN); 4203 *R2TSN += 1; 4204 4205 task->r2t_datasn = 0; /* next expected datasn to ack */ 4206 4207 to_be32(&rsph->buffer_offset, (uint32_t)offset); 4208 to_be32(&rsph->desired_xfer_len, (uint32_t)len); 4209 task->desired_data_transfer_length = (size_t)len; 4210 4211 /* we need to hold onto this task/cmd because until the PDU has been 4212 * written out */ 4213 rsp_pdu->task = task; 4214 task->scsi.ref++; 4215 4216 spdk_iscsi_write_pdu(conn, rsp_pdu); 4217 4218 return SPDK_SUCCESS; 4219 } 4220 4221 int spdk_iscsi_send_nopin(struct spdk_iscsi_conn *conn) 4222 { 4223 struct spdk_iscsi_pdu *rsp_pdu; 4224 struct iscsi_bhs_nop_in *rsp; 4225 4226 /* Only send nopin if we have logged in and are in a normal session. */ 4227 if (conn->sess == NULL || 4228 !conn->full_feature || 4229 !spdk_iscsi_param_eq_val(conn->sess->params, "SessionType", "Normal")) { 4230 return SPDK_SUCCESS; 4231 } 4232 4233 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 4234 "send NOPIN isid=%"PRIx64", tsih=%u, cid=%u\n", 4235 conn->sess->isid, conn->sess->tsih, conn->cid); 4236 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 4237 "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n", 4238 conn->StatSN, conn->sess->ExpCmdSN, 4239 conn->sess->MaxCmdSN); 4240 4241 rsp_pdu = spdk_get_pdu(); 4242 rsp = (struct iscsi_bhs_nop_in *) &rsp_pdu->bhs; 4243 rsp_pdu->data = NULL; 4244 4245 /* 4246 * spdk_get_pdu() memset's the PDU for us, so only fill out the needed 4247 * fields. 4248 */ 4249 rsp->opcode = ISCSI_OP_NOPIN; 4250 rsp->flags = 0x80; 4251 /* 4252 * Technically the to_be32() is not needed here, since 4253 * to_be32(0xFFFFFFFU) returns 0xFFFFFFFFU. 4254 */ 4255 to_be32(&rsp->itt, 0xFFFFFFFFU); 4256 to_be32(&rsp->ttt, conn->id); 4257 to_be32(&rsp->stat_sn, conn->StatSN); 4258 to_be32(&rsp->exp_cmd_sn, conn->sess->ExpCmdSN); 4259 to_be32(&rsp->max_cmd_sn, conn->sess->MaxCmdSN); 4260 4261 spdk_iscsi_write_pdu(conn, rsp_pdu); 4262 conn->nop_outstanding = true; 4263 4264 return SPDK_SUCCESS; 4265 } 4266 4267 static void 4268 spdk_init_login_reject_response(struct spdk_iscsi_pdu *pdu, struct spdk_iscsi_pdu *rsp_pdu) 4269 { 4270 struct iscsi_bhs_login_rsp *rsph; 4271 4272 memset(rsp_pdu, 0, sizeof(struct spdk_iscsi_pdu)); 4273 rsph = (struct iscsi_bhs_login_rsp *)&rsp_pdu->bhs; 4274 rsph->version_max = ISCSI_VERSION; 4275 rsph->version_act = ISCSI_VERSION; 4276 rsph->opcode = ISCSI_OP_LOGIN_RSP; 4277 rsph->status_class = ISCSI_CLASS_INITIATOR_ERROR; 4278 rsph->status_detail = ISCSI_LOGIN_INVALID_LOGIN_REQUEST; 4279 rsph->itt = pdu->bhs.itt; 4280 } 4281 4282 int 4283 spdk_iscsi_execute(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) 4284 { 4285 int opcode; 4286 int rc; 4287 struct spdk_iscsi_pdu *rsp_pdu = NULL; 4288 uint32_t ExpStatSN; 4289 uint32_t QCmdSN; 4290 int I_bit; 4291 struct spdk_iscsi_sess *sess; 4292 struct iscsi_bhs_scsi_req *reqh; 4293 4294 if (pdu == NULL) 4295 return -1; 4296 4297 opcode = pdu->bhs.opcode; 4298 reqh = (struct iscsi_bhs_scsi_req *)&pdu->bhs; 4299 pdu->cmd_sn = from_be32(&reqh->cmd_sn); 4300 4301 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "opcode %x\n", opcode); 4302 4303 if (opcode == ISCSI_OP_LOGIN) { 4304 rc = spdk_iscsi_op_login(conn, pdu); 4305 if (rc < 0) { 4306 SPDK_ERRLOG("iscsi_op_login() failed\n"); 4307 } 4308 return rc; 4309 } 4310 4311 /* connection in login phase but receive non-login opcode 4312 * return response code 0x020b to initiator. 4313 * */ 4314 if (!conn->full_feature && conn->state == ISCSI_CONN_STATE_RUNNING) { 4315 rsp_pdu = spdk_get_pdu(); 4316 spdk_init_login_reject_response(pdu, rsp_pdu); 4317 spdk_iscsi_write_pdu(conn, rsp_pdu); 4318 SPDK_ERRLOG("Received opcode %d in login phase\n", opcode); 4319 return SPDK_ISCSI_LOGIN_ERROR_RESPONSE; 4320 } else if (conn->state == ISCSI_CONN_STATE_INVALID) { 4321 SPDK_ERRLOG("before Full Feature\n"); 4322 return SPDK_ISCSI_CONNECTION_FATAL; 4323 } 4324 4325 sess = conn->sess; 4326 if (!sess) { 4327 SPDK_ERRLOG("Connection has no associated session!\n"); 4328 return SPDK_ISCSI_CONNECTION_FATAL; 4329 } 4330 I_bit = reqh->immediate; 4331 if (I_bit == 0) { 4332 if (SN32_LT(pdu->cmd_sn, sess->ExpCmdSN) || 4333 SN32_GT(pdu->cmd_sn, sess->MaxCmdSN)) { 4334 if (sess->session_type == SESSION_TYPE_NORMAL && 4335 opcode != ISCSI_OP_SCSI_DATAOUT) { 4336 SPDK_ERRLOG("CmdSN(%u) ignore (ExpCmdSN=%u, MaxCmdSN=%u)\n", 4337 pdu->cmd_sn, sess->ExpCmdSN, sess->MaxCmdSN); 4338 4339 if (sess->ErrorRecoveryLevel >= 1) 4340 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Skip the error in" 4341 " ERL 1 and 2\n"); 4342 else 4343 return SPDK_PDU_FATAL; 4344 } 4345 } 4346 } else if (pdu->cmd_sn != sess->ExpCmdSN) { 4347 SPDK_ERRLOG("CmdSN(%u) error ExpCmdSN=%u\n", pdu->cmd_sn, sess->ExpCmdSN); 4348 4349 if (sess->ErrorRecoveryLevel >= 1) { 4350 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Skip the error in" 4351 " ERL 1 and 2\n"); 4352 } else if (opcode != ISCSI_OP_NOPOUT) { 4353 /* 4354 * The Linux initiator does not send valid CmdSNs for 4355 * nopout under heavy load, so do not close the 4356 * connection in that case. 4357 */ 4358 return SPDK_ISCSI_CONNECTION_FATAL; 4359 } 4360 } 4361 4362 ExpStatSN = from_be32(&reqh->exp_stat_sn); 4363 if (SN32_GT(ExpStatSN, conn->StatSN)) { 4364 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "StatSN(%u) advanced\n", 4365 ExpStatSN); 4366 ExpStatSN = conn->StatSN; 4367 } 4368 4369 if (sess->ErrorRecoveryLevel >= 1) 4370 spdk_remove_acked_pdu(conn, ExpStatSN); 4371 4372 if (opcode == ISCSI_OP_NOPOUT || opcode == ISCSI_OP_SCSI) { 4373 QCmdSN = sess->MaxCmdSN - sess->ExpCmdSN + 1; 4374 QCmdSN += sess->queue_depth; 4375 if (SN32_LT(ExpStatSN + QCmdSN, conn->StatSN)) { 4376 SPDK_ERRLOG("StatSN(%u/%u) QCmdSN(%u) error\n", 4377 ExpStatSN, conn->StatSN, QCmdSN); 4378 return SPDK_ISCSI_CONNECTION_FATAL; 4379 } 4380 } 4381 4382 if (!I_bit && opcode != ISCSI_OP_SCSI_DATAOUT) 4383 sess->ExpCmdSN++; 4384 4385 switch (opcode) { 4386 case ISCSI_OP_NOPOUT: 4387 rc = spdk_iscsi_op_nopout(conn, pdu); 4388 if (rc < 0) { 4389 SPDK_ERRLOG("spdk_iscsi_op_nopout() failed\n"); 4390 return rc; 4391 } 4392 break; 4393 4394 case ISCSI_OP_SCSI: 4395 rc = spdk_iscsi_op_scsi(conn, pdu); 4396 if (rc < 0) { 4397 SPDK_ERRLOG("spdk_iscsi_op_scsi() failed\n"); 4398 return rc; 4399 } 4400 break; 4401 case ISCSI_OP_TASK: 4402 rc = spdk_iscsi_op_task(conn, pdu); 4403 if (rc < 0) { 4404 SPDK_ERRLOG("spdk_iscsi_op_task() failed\n"); 4405 return rc; 4406 } 4407 break; 4408 4409 case ISCSI_OP_TEXT: 4410 rc = spdk_iscsi_op_text(conn, pdu); 4411 if (rc < 0) { 4412 SPDK_ERRLOG("spdk_iscsi_op_text() failed\n"); 4413 return rc; 4414 } 4415 break; 4416 4417 case ISCSI_OP_LOGOUT: 4418 rc = spdk_iscsi_op_logout(conn, pdu); 4419 if (rc < 0) { 4420 SPDK_ERRLOG("spdk_iscsi_op_logout() failed\n"); 4421 return rc; 4422 } 4423 break; 4424 4425 case ISCSI_OP_SCSI_DATAOUT: 4426 rc = spdk_iscsi_op_data(conn, pdu); 4427 if (rc < 0) { 4428 SPDK_ERRLOG("spdk_iscsi_op_data() failed\n"); 4429 return rc; 4430 } 4431 break; 4432 4433 case ISCSI_OP_SNACK: 4434 rc = spdk_iscsi_op_snack(conn, pdu); 4435 if (rc < 0) { 4436 SPDK_ERRLOG("spdk_iscsi_op_snack() failed\n"); 4437 return rc; 4438 } 4439 break; 4440 4441 default: 4442 SPDK_ERRLOG("unsupported opcode %x\n", opcode); 4443 rc = spdk_iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); 4444 if (rc < 0) { 4445 SPDK_ERRLOG("spdk_iscsi_reject() failed\n"); 4446 return rc; 4447 } 4448 break; 4449 } 4450 4451 return 0; 4452 } 4453 4454 void spdk_free_sess(struct spdk_iscsi_sess *sess) 4455 { 4456 if (sess == NULL) 4457 return; 4458 4459 sess->tag = 0; 4460 sess->target = NULL; 4461 sess->session_type = SESSION_TYPE_INVALID; 4462 spdk_iscsi_param_free(sess->params); 4463 free(sess->conns); 4464 spdk_scsi_port_free(&sess->initiator_port); 4465 rte_mempool_put(g_spdk_iscsi.session_pool, (void *)sess); 4466 } 4467 4468 static int 4469 spdk_create_iscsi_sess(struct spdk_iscsi_conn *conn, 4470 struct spdk_iscsi_tgt_node *target, 4471 enum session_type session_type) 4472 { 4473 struct spdk_iscsi_sess *sess; 4474 int rc; 4475 4476 rc = rte_mempool_get(g_spdk_iscsi.session_pool, (void **)&sess); 4477 if ((rc < 0) || !sess) { 4478 SPDK_ERRLOG("Unable to get session object\n"); 4479 SPDK_ERRLOG("MaxSessions set to %d\n", g_spdk_iscsi.MaxSessions); 4480 return -ENOMEM; 4481 } 4482 4483 /* configuration values */ 4484 pthread_mutex_lock(&g_spdk_iscsi.mutex); 4485 4486 if (target != NULL) 4487 pthread_mutex_lock(&target->mutex); 4488 4489 sess->MaxConnections = g_spdk_iscsi.MaxConnectionsPerSession; 4490 sess->MaxOutstandingR2T = DEFAULT_MAXOUTSTANDINGR2T; 4491 4492 sess->DefaultTime2Wait = g_spdk_iscsi.DefaultTime2Wait; 4493 sess->DefaultTime2Retain = g_spdk_iscsi.DefaultTime2Retain; 4494 sess->FirstBurstLength = g_spdk_iscsi.FirstBurstLength; 4495 sess->MaxBurstLength = g_spdk_iscsi.MaxBurstLength; 4496 sess->InitialR2T = g_spdk_iscsi.InitialR2T; 4497 sess->ImmediateData = g_spdk_iscsi.ImmediateData; 4498 sess->DataPDUInOrder = g_spdk_iscsi.DataPDUInOrder; 4499 sess->DataSequenceInOrder = g_spdk_iscsi.DataSequenceInOrder; 4500 sess->ErrorRecoveryLevel = g_spdk_iscsi.ErrorRecoveryLevel; 4501 4502 if (target != NULL) 4503 pthread_mutex_unlock(&target->mutex); 4504 4505 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 4506 4507 sess->tag = conn->portal->group->tag; 4508 4509 sess->conns = malloc(sizeof(*sess->conns) * sess->MaxConnections); 4510 if (!sess->conns) { 4511 perror("conns"); 4512 return -ENOMEM; 4513 } 4514 4515 memset(sess->conns, 0, sizeof(*sess->conns) * sess->MaxConnections); 4516 sess->connections = 0; 4517 4518 sess->conns[sess->connections] = conn; 4519 sess->connections++; 4520 4521 sess->params = NULL; 4522 sess->target = NULL; 4523 sess->isid = 0; 4524 sess->session_type = session_type; 4525 sess->current_text_itt = 0xffffffffU; 4526 4527 /* set default params */ 4528 rc = spdk_iscsi_sess_params_init(&sess->params); 4529 if (rc < 0) { 4530 SPDK_ERRLOG("iscsi_sess_params_init() failed\n"); 4531 goto error_return; 4532 } 4533 /* replace with config value */ 4534 rc = spdk_iscsi_param_set_int(sess->params, "MaxConnections", 4535 sess->MaxConnections); 4536 if (rc < 0) { 4537 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4538 goto error_return; 4539 } 4540 4541 rc = spdk_iscsi_param_set_int(sess->params, "MaxOutstandingR2T", 4542 sess->MaxOutstandingR2T); 4543 if (rc < 0) { 4544 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4545 goto error_return; 4546 } 4547 4548 rc = spdk_iscsi_param_set_int(sess->params, "DefaultTime2Wait", 4549 sess->DefaultTime2Wait); 4550 if (rc < 0) { 4551 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4552 goto error_return; 4553 } 4554 4555 rc = spdk_iscsi_param_set_int(sess->params, "DefaultTime2Retain", 4556 sess->DefaultTime2Retain); 4557 if (rc < 0) { 4558 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4559 goto error_return; 4560 } 4561 4562 rc = spdk_iscsi_param_set_int(sess->params, "FirstBurstLength", 4563 sess->FirstBurstLength); 4564 if (rc < 0) { 4565 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4566 goto error_return; 4567 } 4568 4569 rc = spdk_iscsi_param_set_int(sess->params, "MaxBurstLength", 4570 sess->MaxBurstLength); 4571 if (rc < 0) { 4572 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4573 goto error_return; 4574 } 4575 4576 rc = spdk_iscsi_param_set(sess->params, "InitialR2T", 4577 sess->InitialR2T ? "Yes" : "No"); 4578 if (rc < 0) { 4579 SPDK_ERRLOG("iscsi_param_set() failed\n"); 4580 goto error_return; 4581 } 4582 4583 rc = spdk_iscsi_param_set(sess->params, "ImmediateData", 4584 sess->ImmediateData ? "Yes" : "No"); 4585 if (rc < 0) { 4586 SPDK_ERRLOG("iscsi_param_set() failed\n"); 4587 goto error_return; 4588 } 4589 4590 rc = spdk_iscsi_param_set(sess->params, "DataPDUInOrder", 4591 sess->DataPDUInOrder ? "Yes" : "No"); 4592 if (rc < 0) { 4593 SPDK_ERRLOG("iscsi_param_set() failed\n"); 4594 goto error_return; 4595 } 4596 4597 rc = spdk_iscsi_param_set(sess->params, "DataSequenceInOrder", 4598 sess->DataSequenceInOrder ? "Yes" : "No"); 4599 if (rc < 0) { 4600 SPDK_ERRLOG("iscsi_param_set() failed\n"); 4601 goto error_return; 4602 } 4603 4604 rc = spdk_iscsi_param_set_int(sess->params, "ErrorRecoveryLevel", 4605 sess->ErrorRecoveryLevel); 4606 if (rc < 0) { 4607 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4608 goto error_return; 4609 } 4610 4611 /* realloc buffer */ 4612 rc = spdk_iscsi_param_set_int(conn->params, "MaxRecvDataSegmentLength", 4613 conn->MaxRecvDataSegmentLength); 4614 if (rc < 0) { 4615 SPDK_ERRLOG("iscsi_param_set_int() failed\n"); 4616 goto error_return; 4617 } 4618 4619 /* sess for first connection of session */ 4620 conn->sess = sess; 4621 return 0; 4622 4623 error_return: 4624 spdk_free_sess(sess); 4625 conn->sess = NULL; 4626 return -1; 4627 } 4628 4629 static struct spdk_iscsi_sess * 4630 spdk_get_iscsi_sess_by_tsih(uint16_t tsih) 4631 { 4632 struct spdk_iscsi_sess *session; 4633 4634 if (tsih == 0 || tsih > g_spdk_iscsi.MaxSessions) { 4635 return NULL; 4636 } 4637 4638 session = g_spdk_iscsi.session[tsih - 1]; 4639 assert(tsih == session->tsih); 4640 4641 return session; 4642 } 4643 4644 static int 4645 spdk_append_iscsi_sess(struct spdk_iscsi_conn *conn, 4646 const char *initiator_port_name, uint16_t tsih, uint16_t cid) 4647 { 4648 struct spdk_iscsi_sess *sess; 4649 4650 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, 4651 "append session: init port name=%s, tsih=%u, cid=%u\n", 4652 initiator_port_name, tsih, cid); 4653 4654 sess = spdk_get_iscsi_sess_by_tsih(tsih); 4655 if (sess == NULL) { 4656 SPDK_ERRLOG("spdk_get_iscsi_sess_by_tsih failed\n"); 4657 return -1; 4658 } 4659 if ((conn->portal->group->tag != sess->tag) || 4660 (strcasecmp(initiator_port_name, spdk_scsi_port_get_name(sess->initiator_port)) != 0) || 4661 (conn->target != sess->target)) { 4662 /* no match */ 4663 SPDK_ERRLOG("no MCS session for init port name=%s, tsih=%d, cid=%d\n", 4664 initiator_port_name, tsih, cid); 4665 return -1; 4666 } 4667 4668 if (sess->connections >= sess->MaxConnections) { 4669 /* no slot for connection */ 4670 SPDK_ERRLOG("too many connections for init port name=%s, tsih=%d, cid=%d\n", 4671 initiator_port_name, tsih, cid); 4672 return -1; 4673 } 4674 4675 SPDK_DEBUGLOG(SPDK_TRACE_ISCSI, "Connections (tsih %d): %d\n", sess->tsih, sess->connections); 4676 conn->sess = sess; 4677 4678 /* 4679 * TODO: need a mutex or other sync mechanism to protect the session's 4680 * connection list. 4681 */ 4682 sess->conns[sess->connections] = conn; 4683 sess->connections++; 4684 4685 return 0; 4686 } 4687 4688 void 4689 spdk_iscsi_shutdown(void) 4690 { 4691 spdk_iscsi_portal_grp_close_all(); 4692 spdk_shutdown_iscsi_conns(); 4693 } 4694 4695 bool spdk_iscsi_is_deferred_free_pdu(struct spdk_iscsi_pdu *pdu) 4696 { 4697 if (pdu == NULL) 4698 return false; 4699 4700 if (pdu->bhs.opcode == ISCSI_OP_R2T || 4701 pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) 4702 return true; 4703 4704 return false; 4705 } 4706