1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/conf.h> 27 #include <sys/stat.h> 28 #include <sys/file.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/modctl.h> 32 #include <sys/priv.h> 33 #include <sys/cpuvar.h> 34 #include <sys/socket.h> 35 #include <sys/strsubr.h> 36 #include <sys/sysmacros.h> 37 #include <sys/sdt.h> 38 #include <netinet/tcp.h> 39 #include <inet/tcp.h> 40 #include <sys/socketvar.h> 41 #include <sys/pathname.h> 42 #include <sys/fs/snode.h> 43 #include <sys/fs/dv_node.h> 44 #include <sys/vnode.h> 45 #include <netinet/in.h> 46 #include <net/if.h> 47 #include <sys/sockio.h> 48 #include <sys/ksocket.h> 49 #include <sys/idm/idm.h> 50 #include <sys/idm/idm_so.h> 51 #include <sys/idm/idm_text.h> 52 53 /* 54 * in6addr_any is currently all zeroes, but use the macro in case this 55 * ever changes. 56 */ 57 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 58 59 static void idm_sorx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status); 60 static void idm_sorx_addl_pdu_cb(idm_pdu_t *pdu, idm_status_t status); 61 static void idm_sotx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status); 62 63 static idm_status_t idm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so); 64 static void idm_so_conn_destroy_common(idm_conn_t *ic); 65 static void idm_so_conn_connect_common(idm_conn_t *ic); 66 67 static void idm_set_ini_preconnect_options(idm_so_conn_t *sc); 68 static void idm_set_ini_postconnect_options(idm_so_conn_t *sc); 69 static void idm_set_tgt_connect_options(ksocket_t so); 70 static idm_status_t idm_i_so_tx(idm_pdu_t *pdu); 71 72 static idm_status_t idm_sorecvdata(idm_conn_t *ic, idm_pdu_t *pdu); 73 static void idm_so_send_rtt_data(idm_conn_t *ic, idm_task_t *idt, 74 idm_buf_t *idb, uint32_t offset, uint32_t length); 75 static void idm_so_send_rtt_data_done(idm_task_t *idt, idm_buf_t *idb); 76 static idm_status_t idm_so_send_buf_region(idm_task_t *idt, 77 idm_buf_t *idb, uint32_t buf_region_offset, uint32_t buf_region_length); 78 79 static uint32_t idm_fill_iov(idm_pdu_t *pdu, idm_buf_t *idb, 80 uint32_t ro, uint32_t dlength); 81 82 static idm_status_t idm_so_handle_digest(idm_conn_t *it, 83 nvpair_t *digest_choice, const idm_kv_xlate_t *ikvx); 84 85 /* 86 * Transport ops prototypes 87 */ 88 static void idm_so_tx(idm_conn_t *ic, idm_pdu_t *pdu); 89 static idm_status_t idm_so_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb); 90 static idm_status_t idm_so_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb); 91 static void idm_so_rx_datain(idm_conn_t *ic, idm_pdu_t *pdu); 92 static void idm_so_rx_rtt(idm_conn_t *ic, idm_pdu_t *pdu); 93 static void idm_so_rx_dataout(idm_conn_t *ic, idm_pdu_t *pdu); 94 static idm_status_t idm_so_free_task_rsrc(idm_task_t *idt); 95 static kv_status_t idm_so_negotiate_key_values(idm_conn_t *it, 96 nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl); 97 static void idm_so_notice_key_values(idm_conn_t *it, 98 nvlist_t *negotiated_nvl); 99 static boolean_t idm_so_conn_is_capable(idm_conn_req_t *ic, 100 idm_transport_caps_t *caps); 101 static idm_status_t idm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen); 102 static void idm_so_buf_free(idm_buf_t *idb); 103 static idm_status_t idm_so_buf_setup(idm_buf_t *idb); 104 static void idm_so_buf_teardown(idm_buf_t *idb); 105 static idm_status_t idm_so_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is); 106 static void idm_so_tgt_svc_destroy(idm_svc_t *is); 107 static idm_status_t idm_so_tgt_svc_online(idm_svc_t *is); 108 static void idm_so_tgt_svc_offline(idm_svc_t *is); 109 static void idm_so_tgt_conn_destroy(idm_conn_t *ic); 110 static idm_status_t idm_so_tgt_conn_connect(idm_conn_t *ic); 111 static void idm_so_conn_disconnect(idm_conn_t *ic); 112 static idm_status_t idm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic); 113 static void idm_so_ini_conn_destroy(idm_conn_t *ic); 114 static idm_status_t idm_so_ini_conn_connect(idm_conn_t *ic); 115 116 /* 117 * IDM Native Sockets transport operations 118 */ 119 static 120 idm_transport_ops_t idm_so_transport_ops = { 121 idm_so_tx, /* it_tx_pdu */ 122 idm_so_buf_tx_to_ini, /* it_buf_tx_to_ini */ 123 idm_so_buf_rx_from_ini, /* it_buf_rx_from_ini */ 124 idm_so_rx_datain, /* it_rx_datain */ 125 idm_so_rx_rtt, /* it_rx_rtt */ 126 idm_so_rx_dataout, /* it_rx_dataout */ 127 NULL, /* it_alloc_conn_rsrc */ 128 NULL, /* it_free_conn_rsrc */ 129 NULL, /* it_tgt_enable_datamover */ 130 NULL, /* it_ini_enable_datamover */ 131 NULL, /* it_conn_terminate */ 132 idm_so_free_task_rsrc, /* it_free_task_rsrc */ 133 idm_so_negotiate_key_values, /* it_negotiate_key_values */ 134 idm_so_notice_key_values, /* it_notice_key_values */ 135 idm_so_conn_is_capable, /* it_conn_is_capable */ 136 idm_so_buf_alloc, /* it_buf_alloc */ 137 idm_so_buf_free, /* it_buf_free */ 138 idm_so_buf_setup, /* it_buf_setup */ 139 idm_so_buf_teardown, /* it_buf_teardown */ 140 idm_so_tgt_svc_create, /* it_tgt_svc_create */ 141 idm_so_tgt_svc_destroy, /* it_tgt_svc_destroy */ 142 idm_so_tgt_svc_online, /* it_tgt_svc_online */ 143 idm_so_tgt_svc_offline, /* it_tgt_svc_offline */ 144 idm_so_tgt_conn_destroy, /* it_tgt_conn_destroy */ 145 idm_so_tgt_conn_connect, /* it_tgt_conn_connect */ 146 idm_so_conn_disconnect, /* it_tgt_conn_disconnect */ 147 idm_so_ini_conn_create, /* it_ini_conn_create */ 148 idm_so_ini_conn_destroy, /* it_ini_conn_destroy */ 149 idm_so_ini_conn_connect, /* it_ini_conn_connect */ 150 idm_so_conn_disconnect /* it_ini_conn_disconnect */ 151 }; 152 153 /* 154 * idm_so_init() 155 * Sockets transport initialization 156 */ 157 void 158 idm_so_init(idm_transport_t *it) 159 { 160 /* Cache for IDM Data and R2T Transmit PDU's */ 161 idm.idm_sotx_pdu_cache = kmem_cache_create("idm_tx_pdu_cache", 162 sizeof (idm_pdu_t) + sizeof (iscsi_hdr_t), 8, 163 &idm_sotx_pdu_constructor, NULL, NULL, NULL, NULL, KM_SLEEP); 164 165 /* Cache for IDM Receive PDU's */ 166 idm.idm_sorx_pdu_cache = kmem_cache_create("idm_rx_pdu_cache", 167 sizeof (idm_pdu_t) + IDM_SORX_CACHE_HDRLEN, 8, 168 &idm_sorx_pdu_constructor, NULL, NULL, NULL, NULL, KM_SLEEP); 169 170 /* Set the sockets transport ops */ 171 it->it_ops = &idm_so_transport_ops; 172 } 173 174 /* 175 * idm_so_fini() 176 * Sockets transport teardown 177 */ 178 void 179 idm_so_fini(void) 180 { 181 kmem_cache_destroy(idm.idm_sotx_pdu_cache); 182 kmem_cache_destroy(idm.idm_sorx_pdu_cache); 183 } 184 185 ksocket_t 186 idm_socreate(int domain, int type, int protocol) 187 { 188 ksocket_t ks; 189 190 if (!ksocket_socket(&ks, domain, type, protocol, KSOCKET_NOSLEEP, 191 CRED())) { 192 return (ks); 193 } else { 194 return (NULL); 195 } 196 } 197 198 /* 199 * idm_soshutdown will disconnect the socket and prevent subsequent PDU 200 * reception and transmission. The sonode still exists but its state 201 * gets modified to indicate it is no longer connected. Calls to 202 * idm_sorecv/idm_iov_sorecv will return so idm_soshutdown can be used 203 * regain control of a thread stuck in idm_sorecv. 204 */ 205 void 206 idm_soshutdown(ksocket_t so) 207 { 208 (void) ksocket_shutdown(so, SHUT_RDWR, CRED()); 209 } 210 211 /* 212 * idm_sodestroy releases all resources associated with a socket previously 213 * created with idm_socreate. The socket must be shutdown using 214 * idm_soshutdown before the socket is destroyed with idm_sodestroy, 215 * otherwise undefined behavior will result. 216 */ 217 void 218 idm_sodestroy(ksocket_t ks) 219 { 220 (void) ksocket_close(ks, CRED()); 221 } 222 223 /* 224 * IP address filter functions to flag addresses that should not 225 * go out to initiators through discovery. 226 */ 227 static boolean_t 228 idm_v4_addr_okay(struct in_addr *in_addr) 229 { 230 in_addr_t addr = ntohl(in_addr->s_addr); 231 232 if ((INADDR_NONE == addr) || 233 (IN_MULTICAST(addr)) || 234 ((addr >> IN_CLASSA_NSHIFT) == 0) || 235 ((addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) { 236 return (B_FALSE); 237 } 238 return (B_TRUE); 239 } 240 241 static boolean_t 242 idm_v6_addr_okay(struct in6_addr *addr6) 243 { 244 245 if ((IN6_IS_ADDR_UNSPECIFIED(addr6)) || 246 (IN6_IS_ADDR_LOOPBACK(addr6)) || 247 (IN6_IS_ADDR_MULTICAST(addr6)) || 248 (IN6_IS_ADDR_V4MAPPED(addr6)) || 249 (IN6_IS_ADDR_V4COMPAT(addr6)) || 250 (IN6_IS_ADDR_LINKLOCAL(addr6))) { 251 return (B_FALSE); 252 } 253 return (B_TRUE); 254 } 255 256 /* 257 * idm_get_ipaddr will retrieve a list of IP Addresses which the host is 258 * configured with by sending down a sequence of kernel ioctl to IP STREAMS. 259 */ 260 int 261 idm_get_ipaddr(idm_addr_list_t **ipaddr_p) 262 { 263 ksocket_t so4, so6; 264 struct lifnum lifn; 265 struct lifconf lifc; 266 struct lifreq *lp; 267 int rval; 268 int numifs; 269 int bufsize; 270 void *buf; 271 int i, j, n, rc; 272 struct sockaddr_storage ss; 273 struct sockaddr_in *sin; 274 struct sockaddr_in6 *sin6; 275 idm_addr_t *ip; 276 idm_addr_list_t *ipaddr; 277 int size_ipaddr; 278 279 *ipaddr_p = NULL; 280 size_ipaddr = 0; 281 buf = NULL; 282 283 /* create an ipv4 and ipv6 UDP socket */ 284 if ((so6 = idm_socreate(PF_INET6, SOCK_DGRAM, 0)) == NULL) 285 return (0); 286 if ((so4 = idm_socreate(PF_INET, SOCK_DGRAM, 0)) == NULL) { 287 idm_sodestroy(so6); 288 return (0); 289 } 290 291 292 retry_count: 293 /* snapshot the current number of interfaces */ 294 lifn.lifn_family = PF_UNSPEC; 295 lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; 296 lifn.lifn_count = 0; 297 /* use vp6 for ioctls with unspecified families by default */ 298 if (ksocket_ioctl(so6, SIOCGLIFNUM, (intptr_t)&lifn, &rval, CRED()) 299 != 0) { 300 goto cleanup; 301 } 302 303 numifs = lifn.lifn_count; 304 if (numifs <= 0) { 305 goto cleanup; 306 } 307 308 /* allocate extra room in case more interfaces appear */ 309 numifs += 10; 310 311 /* get the interface names and ip addresses */ 312 bufsize = numifs * sizeof (struct lifreq); 313 buf = kmem_alloc(bufsize, KM_SLEEP); 314 315 lifc.lifc_family = AF_UNSPEC; 316 lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES; 317 lifc.lifc_len = bufsize; 318 lifc.lifc_buf = buf; 319 rc = ksocket_ioctl(so6, SIOCGLIFCONF, (intptr_t)&lifc, &rval, CRED()); 320 if (rc != 0) { 321 goto cleanup; 322 } 323 /* if our extra room is used up, try again */ 324 if (bufsize <= lifc.lifc_len) { 325 kmem_free(buf, bufsize); 326 buf = NULL; 327 goto retry_count; 328 } 329 /* calc actual number of ifconfs */ 330 n = lifc.lifc_len / sizeof (struct lifreq); 331 332 /* get ip address */ 333 if (n > 0) { 334 size_ipaddr = sizeof (idm_addr_list_t) + 335 (n - 1) * sizeof (idm_addr_t); 336 ipaddr = kmem_zalloc(size_ipaddr, KM_SLEEP); 337 } else { 338 goto cleanup; 339 } 340 341 /* 342 * Examine the array of interfaces and filter uninteresting ones 343 */ 344 for (i = 0, j = 0, lp = lifc.lifc_req; i < n; i++, lp++) { 345 346 /* 347 * Copy the address as the SIOCGLIFFLAGS ioctl is destructive 348 */ 349 ss = lp->lifr_addr; 350 /* 351 * fetch the flags using the socket of the correct family 352 */ 353 switch (ss.ss_family) { 354 case AF_INET: 355 rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)lp, 356 &rval, CRED()); 357 break; 358 case AF_INET6: 359 rc = ksocket_ioctl(so6, SIOCGLIFFLAGS, (intptr_t)lp, 360 &rval, CRED()); 361 break; 362 default: 363 continue; 364 } 365 if (rc == 0) { 366 /* 367 * If we got the flags, skip uninteresting 368 * interfaces based on flags 369 */ 370 if ((lp->lifr_flags & IFF_UP) != IFF_UP) 371 continue; 372 if (lp->lifr_flags & 373 (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED)) 374 continue; 375 } 376 377 /* save ip address */ 378 ip = &ipaddr->al_addrs[j]; 379 switch (ss.ss_family) { 380 case AF_INET: 381 sin = (struct sockaddr_in *)&ss; 382 if (!idm_v4_addr_okay(&sin->sin_addr)) 383 continue; 384 ip->a_addr.i_addr.in4 = sin->sin_addr; 385 ip->a_addr.i_insize = sizeof (struct in_addr); 386 break; 387 case AF_INET6: 388 sin6 = (struct sockaddr_in6 *)&ss; 389 if (!idm_v6_addr_okay(&sin6->sin6_addr)) 390 continue; 391 ip->a_addr.i_addr.in6 = sin6->sin6_addr; 392 ip->a_addr.i_insize = sizeof (struct in6_addr); 393 break; 394 default: 395 continue; 396 } 397 j++; 398 } 399 400 if (j == 0) { 401 /* no valid ifaddr */ 402 kmem_free(ipaddr, size_ipaddr); 403 size_ipaddr = 0; 404 ipaddr = NULL; 405 } else { 406 ipaddr->al_out_cnt = j; 407 } 408 409 410 cleanup: 411 idm_sodestroy(so6); 412 idm_sodestroy(so4); 413 414 if (buf != NULL) 415 kmem_free(buf, bufsize); 416 417 *ipaddr_p = ipaddr; 418 return (size_ipaddr); 419 } 420 421 int 422 idm_sorecv(ksocket_t so, void *msg, size_t len) 423 { 424 iovec_t iov; 425 426 ASSERT(so != NULL); 427 ASSERT(len != 0); 428 429 /* 430 * Fill in iovec and receive data 431 */ 432 iov.iov_base = msg; 433 iov.iov_len = len; 434 435 return (idm_iov_sorecv(so, &iov, 1, len)); 436 } 437 438 /* 439 * idm_sosendto - Sends a buffered data on a non-connected socket. 440 * 441 * This function puts the data provided on the wire by calling sosendmsg. 442 * It will return only when all the data has been sent or if an error 443 * occurs. 444 * 445 * Returns 0 for success, the socket errno value if sosendmsg fails, and 446 * -1 if sosendmsg returns success but uio_resid != 0 447 */ 448 int 449 idm_sosendto(ksocket_t so, void *buff, size_t len, 450 struct sockaddr *name, socklen_t namelen) 451 { 452 struct msghdr msg; 453 struct iovec iov[1]; 454 int error; 455 size_t sent = 0; 456 457 iov[0].iov_base = buff; 458 iov[0].iov_len = len; 459 460 /* Initialization of the message header. */ 461 bzero(&msg, sizeof (msg)); 462 msg.msg_iov = iov; 463 msg.msg_iovlen = 1; 464 msg.msg_name = name; 465 msg.msg_namelen = namelen; 466 467 if ((error = ksocket_sendmsg(so, &msg, 0, &sent, CRED())) == 0) { 468 /* Data sent */ 469 if (sent == len) { 470 /* All data sent. Success. */ 471 return (0); 472 } else { 473 /* Not all data was sent. Failure */ 474 return (-1); 475 } 476 } 477 478 /* Send failed */ 479 return (error); 480 } 481 482 /* 483 * idm_iov_sosend - Sends an iovec on a connection. 484 * 485 * This function puts the data provided on the wire by calling sosendmsg. 486 * It will return only when all the data has been sent or if an error 487 * occurs. 488 * 489 * Returns 0 for success, the socket errno value if sosendmsg fails, and 490 * -1 if sosendmsg returns success but uio_resid != 0 491 */ 492 int 493 idm_iov_sosend(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len) 494 { 495 struct msghdr msg; 496 int error; 497 size_t sent = 0; 498 499 ASSERT(iop != NULL); 500 501 /* Initialization of the message header. */ 502 bzero(&msg, sizeof (msg)); 503 msg.msg_iov = iop; 504 msg.msg_iovlen = iovlen; 505 506 if ((error = ksocket_sendmsg(so, &msg, 0, &sent, CRED())) 507 == 0) { 508 /* Data sent */ 509 if (sent == total_len) { 510 /* All data sent. Success. */ 511 return (0); 512 } else { 513 /* Not all data was sent. Failure */ 514 return (-1); 515 } 516 } 517 518 /* Send failed */ 519 return (error); 520 } 521 522 /* 523 * idm_iov_sorecv - Receives an iovec from a connection 524 * 525 * This function gets the data asked for from the socket. It will return 526 * only when all the requested data has been retrieved or if an error 527 * occurs. 528 * 529 * Returns 0 for success, the socket errno value if sorecvmsg fails, and 530 * -1 if sorecvmsg returns success but uio_resid != 0 531 */ 532 int 533 idm_iov_sorecv(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len) 534 { 535 struct msghdr msg; 536 int error; 537 size_t recv; 538 int flags; 539 540 ASSERT(iop != NULL); 541 542 /* Initialization of the message header. */ 543 bzero(&msg, sizeof (msg)); 544 msg.msg_iov = iop; 545 msg.msg_iovlen = iovlen; 546 flags = MSG_WAITALL; 547 548 if ((error = ksocket_recvmsg(so, &msg, flags, &recv, CRED())) 549 == 0) { 550 /* Received data */ 551 if (recv == total_len) { 552 /* All requested data received. Success */ 553 return (0); 554 } else { 555 /* 556 * Not all data was received. The connection has 557 * probably failed. 558 */ 559 return (-1); 560 } 561 } 562 563 /* Receive failed */ 564 return (error); 565 } 566 567 static void 568 idm_set_ini_preconnect_options(idm_so_conn_t *sc) 569 { 570 int conn_abort = 10000; 571 int conn_notify = 2000; 572 int abort = 30000; 573 574 /* Pre-connect socket options */ 575 (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, 576 TCP_CONN_NOTIFY_THRESHOLD, (char *)&conn_notify, sizeof (int), 577 CRED()); 578 (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, 579 TCP_CONN_ABORT_THRESHOLD, (char *)&conn_abort, sizeof (int), 580 CRED()); 581 (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, TCP_ABORT_THRESHOLD, 582 (char *)&abort, sizeof (int), CRED()); 583 } 584 585 static void 586 idm_set_ini_postconnect_options(idm_so_conn_t *sc) 587 { 588 int32_t rcvbuf = IDM_RCVBUF_SIZE; 589 int32_t sndbuf = IDM_SNDBUF_SIZE; 590 const int on = 1; 591 592 /* Set postconnect options */ 593 (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, TCP_NODELAY, 594 (char *)&on, sizeof (int), CRED()); 595 (void) ksocket_setsockopt(sc->ic_so, SOL_SOCKET, SO_RCVBUF, 596 (char *)&rcvbuf, sizeof (int), CRED()); 597 (void) ksocket_setsockopt(sc->ic_so, SOL_SOCKET, SO_SNDBUF, 598 (char *)&sndbuf, sizeof (int), CRED()); 599 } 600 601 static void 602 idm_set_tgt_connect_options(ksocket_t ks) 603 { 604 int32_t rcvbuf = IDM_RCVBUF_SIZE; 605 int32_t sndbuf = IDM_SNDBUF_SIZE; 606 const int on = 1; 607 608 /* Set connect options */ 609 (void) ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVBUF, 610 (char *)&rcvbuf, sizeof (int), CRED()); 611 (void) ksocket_setsockopt(ks, SOL_SOCKET, SO_SNDBUF, 612 (char *)&sndbuf, sizeof (int), CRED()); 613 (void) ksocket_setsockopt(ks, IPPROTO_TCP, TCP_NODELAY, 614 (char *)&on, sizeof (on), CRED()); 615 } 616 617 static uint32_t 618 n2h24(const uchar_t *ptr) 619 { 620 return ((ptr[0] << 16) | (ptr[1] << 8) | ptr[2]); 621 } 622 623 624 static idm_status_t 625 idm_sorecvhdr(idm_conn_t *ic, idm_pdu_t *pdu) 626 { 627 iscsi_hdr_t *bhs; 628 uint32_t hdr_digest_crc; 629 uint32_t crc_calculated; 630 void *new_hdr; 631 int ahslen = 0; 632 int total_len = 0; 633 int iovlen = 0; 634 struct iovec iov[2]; 635 idm_so_conn_t *so_conn; 636 int rc; 637 638 so_conn = ic->ic_transport_private; 639 640 /* 641 * Read BHS 642 */ 643 bhs = pdu->isp_hdr; 644 rc = idm_sorecv(so_conn->ic_so, pdu->isp_hdr, sizeof (iscsi_hdr_t)); 645 if (rc != IDM_STATUS_SUCCESS) { 646 return (IDM_STATUS_FAIL); 647 } 648 649 /* 650 * Check actual AHS length against the amount available in the buffer 651 */ 652 pdu->isp_hdrlen = sizeof (iscsi_hdr_t) + 653 (bhs->hlength * sizeof (uint32_t)); 654 pdu->isp_datalen = n2h24(bhs->dlength); 655 if (bhs->hlength > IDM_SORX_CACHE_AHSLEN) { 656 /* Allocate a new header segment and change the callback */ 657 new_hdr = kmem_alloc(pdu->isp_hdrlen, KM_SLEEP); 658 bcopy(pdu->isp_hdr, new_hdr, sizeof (iscsi_hdr_t)); 659 pdu->isp_hdr = new_hdr; 660 pdu->isp_flags |= IDM_PDU_ADDL_HDR; 661 662 /* 663 * This callback will restore the expected values after 664 * the RX PDU has been processed. 665 */ 666 pdu->isp_callback = idm_sorx_addl_pdu_cb; 667 } 668 669 /* 670 * Setup receipt of additional header and header digest (if enabled). 671 */ 672 if (bhs->hlength > 0) { 673 iov[iovlen].iov_base = (caddr_t)(pdu->isp_hdr + 1); 674 ahslen = pdu->isp_hdrlen - sizeof (iscsi_hdr_t); 675 iov[iovlen].iov_len = ahslen; 676 total_len += iov[iovlen].iov_len; 677 iovlen++; 678 } 679 680 if (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST) { 681 iov[iovlen].iov_base = (caddr_t)&hdr_digest_crc; 682 iov[iovlen].iov_len = sizeof (hdr_digest_crc); 683 total_len += iov[iovlen].iov_len; 684 iovlen++; 685 } 686 687 if ((iovlen != 0) && 688 (idm_iov_sorecv(so_conn->ic_so, &iov[0], iovlen, 689 total_len) != 0)) { 690 return (IDM_STATUS_FAIL); 691 } 692 693 /* 694 * Validate header digest if enabled 695 */ 696 if (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST) { 697 crc_calculated = idm_crc32c(pdu->isp_hdr, 698 sizeof (iscsi_hdr_t) + ahslen); 699 if (crc_calculated != hdr_digest_crc) { 700 /* Invalid Header Digest */ 701 return (IDM_STATUS_HEADER_DIGEST); 702 } 703 } 704 705 return (0); 706 } 707 708 /* 709 * idm_so_ini_conn_create() 710 * Allocate the sockets transport connection resources. 711 */ 712 static idm_status_t 713 idm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic) 714 { 715 ksocket_t so; 716 idm_so_conn_t *so_conn; 717 idm_status_t idmrc; 718 719 so = idm_socreate(cr->cr_domain, cr->cr_type, 720 cr->cr_protocol); 721 if (so == NULL) { 722 return (IDM_STATUS_FAIL); 723 } 724 725 /* Bind the socket if configured to do so */ 726 if (cr->cr_bound) { 727 if (ksocket_bind(so, &cr->cr_bound_addr.sin, 728 SIZEOF_SOCKADDR(&cr->cr_bound_addr.sin), CRED()) != 0) { 729 idm_sodestroy(so); 730 return (IDM_STATUS_FAIL); 731 } 732 } 733 734 idmrc = idm_so_conn_create_common(ic, so); 735 if (idmrc != IDM_STATUS_SUCCESS) { 736 idm_soshutdown(so); 737 idm_sodestroy(so); 738 return (IDM_STATUS_FAIL); 739 } 740 741 so_conn = ic->ic_transport_private; 742 /* Set up socket options */ 743 idm_set_ini_preconnect_options(so_conn); 744 745 return (IDM_STATUS_SUCCESS); 746 } 747 748 /* 749 * idm_so_ini_conn_destroy() 750 * Tear down the sockets transport connection resources. 751 */ 752 static void 753 idm_so_ini_conn_destroy(idm_conn_t *ic) 754 { 755 idm_so_conn_destroy_common(ic); 756 } 757 758 /* 759 * idm_so_ini_conn_connect() 760 * Establish the connection referred to by the handle previously allocated via 761 * idm_so_ini_conn_create(). 762 */ 763 static idm_status_t 764 idm_so_ini_conn_connect(idm_conn_t *ic) 765 { 766 idm_so_conn_t *so_conn; 767 768 so_conn = ic->ic_transport_private; 769 770 if (ksocket_connect(so_conn->ic_so, &ic->ic_ini_dst_addr.sin, 771 (SIZEOF_SOCKADDR(&ic->ic_ini_dst_addr.sin)), CRED()) != 0) { 772 idm_soshutdown(so_conn->ic_so); 773 return (IDM_STATUS_FAIL); 774 } 775 776 idm_so_conn_connect_common(ic); 777 778 idm_set_ini_postconnect_options(so_conn); 779 780 return (IDM_STATUS_SUCCESS); 781 } 782 783 idm_status_t 784 idm_so_tgt_conn_create(idm_conn_t *ic, ksocket_t new_so) 785 { 786 idm_status_t idmrc; 787 788 idmrc = idm_so_conn_create_common(ic, new_so); 789 790 return (idmrc); 791 } 792 793 static void 794 idm_so_tgt_conn_destroy(idm_conn_t *ic) 795 { 796 idm_so_conn_destroy_common(ic); 797 } 798 799 /* 800 * idm_so_tgt_conn_connect() 801 * Establish the connection in ic, passed from idm_tgt_conn_finish(), which 802 * is invoked from the SM as a result of an inbound connection request. 803 */ 804 static idm_status_t 805 idm_so_tgt_conn_connect(idm_conn_t *ic) 806 { 807 idm_so_conn_connect_common(ic); 808 809 return (IDM_STATUS_SUCCESS); 810 } 811 812 static idm_status_t 813 idm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so) 814 { 815 idm_so_conn_t *so_conn; 816 817 so_conn = kmem_zalloc(sizeof (idm_so_conn_t), KM_SLEEP); 818 so_conn->ic_so = new_so; 819 820 ic->ic_transport_private = so_conn; 821 ic->ic_transport_hdrlen = 0; 822 823 /* Set the scoreboarding flag on this connection */ 824 ic->ic_conn_flags |= IDM_CONN_USE_SCOREBOARD; 825 826 /* 827 * Initialize tx thread mutex and list 828 */ 829 mutex_init(&so_conn->ic_tx_mutex, NULL, MUTEX_DEFAULT, NULL); 830 cv_init(&so_conn->ic_tx_cv, NULL, CV_DEFAULT, NULL); 831 list_create(&so_conn->ic_tx_list, sizeof (idm_pdu_t), 832 offsetof(idm_pdu_t, idm_tx_link)); 833 834 return (IDM_STATUS_SUCCESS); 835 } 836 837 static void 838 idm_so_conn_destroy_common(idm_conn_t *ic) 839 { 840 idm_so_conn_t *so_conn = ic->ic_transport_private; 841 842 ic->ic_transport_private = NULL; 843 idm_sodestroy(so_conn->ic_so); 844 list_destroy(&so_conn->ic_tx_list); 845 mutex_destroy(&so_conn->ic_tx_mutex); 846 cv_destroy(&so_conn->ic_tx_cv); 847 848 kmem_free(so_conn, sizeof (idm_so_conn_t)); 849 } 850 851 static void 852 idm_so_conn_connect_common(idm_conn_t *ic) 853 { 854 idm_so_conn_t *so_conn; 855 struct sockaddr_in6 t_addr; 856 socklen_t t_addrlen = 0; 857 858 so_conn = ic->ic_transport_private; 859 bzero(&t_addr, sizeof (struct sockaddr_in6)); 860 t_addrlen = sizeof (struct sockaddr_in6); 861 862 /* Set the local and remote addresses in the idm conn handle */ 863 ksocket_getsockname(so_conn->ic_so, (struct sockaddr *)&t_addr, 864 &t_addrlen, CRED()); 865 bcopy(&t_addr, &ic->ic_laddr, t_addrlen); 866 ksocket_getpeername(so_conn->ic_so, (struct sockaddr *)&t_addr, 867 &t_addrlen, CRED()); 868 bcopy(&t_addr, &ic->ic_raddr, t_addrlen); 869 870 mutex_enter(&ic->ic_mutex); 871 so_conn->ic_tx_thread = thread_create(NULL, 0, idm_sotx_thread, ic, 0, 872 &p0, TS_RUN, minclsyspri); 873 so_conn->ic_rx_thread = thread_create(NULL, 0, idm_sorx_thread, ic, 0, 874 &p0, TS_RUN, minclsyspri); 875 876 while (!so_conn->ic_rx_thread_running || !so_conn->ic_tx_thread_running) 877 cv_wait(&ic->ic_cv, &ic->ic_mutex); 878 mutex_exit(&ic->ic_mutex); 879 } 880 881 /* 882 * idm_so_conn_disconnect() 883 * Shutdown the socket connection and stop the thread 884 */ 885 static void 886 idm_so_conn_disconnect(idm_conn_t *ic) 887 { 888 idm_so_conn_t *so_conn; 889 890 so_conn = ic->ic_transport_private; 891 892 mutex_enter(&ic->ic_mutex); 893 so_conn->ic_rx_thread_running = B_FALSE; 894 so_conn->ic_tx_thread_running = B_FALSE; 895 /* We need to wakeup the TX thread */ 896 mutex_enter(&so_conn->ic_tx_mutex); 897 cv_signal(&so_conn->ic_tx_cv); 898 mutex_exit(&so_conn->ic_tx_mutex); 899 mutex_exit(&ic->ic_mutex); 900 901 /* This should wakeup the RX thread if it is sleeping */ 902 idm_soshutdown(so_conn->ic_so); 903 904 thread_join(so_conn->ic_tx_thread_did); 905 thread_join(so_conn->ic_rx_thread_did); 906 } 907 908 /* 909 * idm_so_tgt_svc_create() 910 * Establish a service on an IP address and port. idm_svc_req_t contains 911 * the service parameters. 912 */ 913 /*ARGSUSED*/ 914 static idm_status_t 915 idm_so_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is) 916 { 917 idm_so_svc_t *so_svc; 918 919 so_svc = kmem_zalloc(sizeof (idm_so_svc_t), KM_SLEEP); 920 921 /* Set the new sockets service in svc handle */ 922 is->is_so_svc = (void *)so_svc; 923 924 return (IDM_STATUS_SUCCESS); 925 } 926 927 /* 928 * idm_so_tgt_svc_destroy() 929 * Teardown sockets resources allocated in idm_so_tgt_svc_create() 930 */ 931 static void 932 idm_so_tgt_svc_destroy(idm_svc_t *is) 933 { 934 /* the socket will have been torn down; free the service */ 935 kmem_free(is->is_so_svc, sizeof (idm_so_svc_t)); 936 } 937 938 /* 939 * idm_so_tgt_svc_online() 940 * Launch a watch thread on the svc allocated in idm_so_tgt_svc_create() 941 */ 942 943 static idm_status_t 944 idm_so_tgt_svc_online(idm_svc_t *is) 945 { 946 idm_so_svc_t *so_svc; 947 idm_svc_req_t *sr = &is->is_svc_req; 948 struct sockaddr_in6 sin6_ip; 949 const uint32_t on = 1; 950 const uint32_t off = 0; 951 952 mutex_enter(&is->is_mutex); 953 so_svc = (idm_so_svc_t *)is->is_so_svc; 954 955 /* 956 * Try creating an IPv6 socket first 957 */ 958 if ((so_svc->is_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) == NULL) { 959 mutex_exit(&is->is_mutex); 960 return (IDM_STATUS_FAIL); 961 } else { 962 bzero(&sin6_ip, sizeof (sin6_ip)); 963 sin6_ip.sin6_family = AF_INET6; 964 sin6_ip.sin6_port = htons(sr->sr_port); 965 sin6_ip.sin6_addr = in6addr_any; 966 967 (void) ksocket_setsockopt(so_svc->is_so, SOL_SOCKET, 968 SO_REUSEADDR, (char *)&on, sizeof (on), CRED()); 969 /* 970 * Turn off SO_MAC_EXEMPT so future sobinds succeed 971 */ 972 (void) ksocket_setsockopt(so_svc->is_so, SOL_SOCKET, 973 SO_MAC_EXEMPT, (char *)&off, sizeof (off), CRED()); 974 975 if (ksocket_bind(so_svc->is_so, (struct sockaddr *)&sin6_ip, 976 sizeof (sin6_ip), CRED()) != 0) { 977 mutex_exit(&is->is_mutex); 978 idm_sodestroy(so_svc->is_so); 979 return (IDM_STATUS_FAIL); 980 } 981 } 982 983 idm_set_tgt_connect_options(so_svc->is_so); 984 985 if (ksocket_listen(so_svc->is_so, 5, CRED()) != 0) { 986 mutex_exit(&is->is_mutex); 987 idm_soshutdown(so_svc->is_so); 988 idm_sodestroy(so_svc->is_so); 989 return (IDM_STATUS_FAIL); 990 } 991 992 /* Launch a watch thread */ 993 so_svc->is_thread = thread_create(NULL, 0, idm_so_svc_port_watcher, 994 is, 0, &p0, TS_RUN, minclsyspri); 995 996 if (so_svc->is_thread == NULL) { 997 /* Failure to launch; teardown the socket */ 998 mutex_exit(&is->is_mutex); 999 idm_soshutdown(so_svc->is_so); 1000 idm_sodestroy(so_svc->is_so); 1001 return (IDM_STATUS_FAIL); 1002 } 1003 ksocket_hold(so_svc->is_so); 1004 /* Wait for the port watcher thread to start */ 1005 while (!so_svc->is_thread_running) 1006 cv_wait(&is->is_cv, &is->is_mutex); 1007 mutex_exit(&is->is_mutex); 1008 1009 return (IDM_STATUS_SUCCESS); 1010 } 1011 1012 /* 1013 * idm_so_tgt_svc_offline 1014 * 1015 * Stop listening on the IP address and port identified by idm_svc_t. 1016 */ 1017 static void 1018 idm_so_tgt_svc_offline(idm_svc_t *is) 1019 { 1020 idm_so_svc_t *so_svc; 1021 mutex_enter(&is->is_mutex); 1022 so_svc = (idm_so_svc_t *)is->is_so_svc; 1023 so_svc->is_thread_running = B_FALSE; 1024 mutex_exit(&is->is_mutex); 1025 1026 /* 1027 * Teardown socket 1028 */ 1029 idm_sodestroy(so_svc->is_so); 1030 1031 /* 1032 * Now we expect the port watcher thread to terminate 1033 */ 1034 thread_join(so_svc->is_thread_did); 1035 } 1036 1037 /* 1038 * Watch thread for target service connection establishment. 1039 */ 1040 void 1041 idm_so_svc_port_watcher(void *arg) 1042 { 1043 idm_svc_t *svc = arg; 1044 ksocket_t new_so; 1045 idm_conn_t *ic; 1046 idm_status_t idmrc; 1047 idm_so_svc_t *so_svc; 1048 int rc; 1049 const uint32_t off = 0; 1050 struct sockaddr_in6 t_addr; 1051 socklen_t t_addrlen; 1052 1053 bzero(&t_addr, sizeof (struct sockaddr_in6)); 1054 t_addrlen = sizeof (struct sockaddr_in6); 1055 mutex_enter(&svc->is_mutex); 1056 1057 so_svc = svc->is_so_svc; 1058 so_svc->is_thread_running = B_TRUE; 1059 so_svc->is_thread_did = so_svc->is_thread->t_did; 1060 1061 cv_signal(&svc->is_cv); 1062 1063 IDM_SVC_LOG(CE_NOTE, "iSCSI service (%p/%d) online", (void *)svc, 1064 svc->is_svc_req.sr_port); 1065 1066 while (so_svc->is_thread_running) { 1067 mutex_exit(&svc->is_mutex); 1068 1069 if ((rc = ksocket_accept(so_svc->is_so, 1070 (struct sockaddr *)&t_addr, &t_addrlen, 1071 &new_so, CRED())) != 0) { 1072 mutex_enter(&svc->is_mutex); 1073 if (rc == ECONNABORTED) 1074 continue; 1075 /* Connection problem */ 1076 break; 1077 } 1078 /* 1079 * Turn off SO_MAC_EXEMPT so future sobinds succeed 1080 */ 1081 (void) ksocket_setsockopt(new_so, SOL_SOCKET, SO_MAC_EXEMPT, 1082 (char *)&off, sizeof (off), CRED()); 1083 1084 idmrc = idm_svc_conn_create(svc, IDM_TRANSPORT_TYPE_SOCKETS, 1085 &ic); 1086 if (idmrc != IDM_STATUS_SUCCESS) { 1087 /* Drop connection */ 1088 idm_soshutdown(new_so); 1089 idm_sodestroy(new_so); 1090 mutex_enter(&svc->is_mutex); 1091 continue; 1092 } 1093 1094 idmrc = idm_so_tgt_conn_create(ic, new_so); 1095 if (idmrc != IDM_STATUS_SUCCESS) { 1096 idm_svc_conn_destroy(ic); 1097 idm_soshutdown(new_so); 1098 idm_sodestroy(new_so); 1099 mutex_enter(&svc->is_mutex); 1100 continue; 1101 } 1102 1103 /* 1104 * Kick the state machine. At CS_S3_XPT_UP the state machine 1105 * will notify the client (target) about the new connection. 1106 */ 1107 idm_conn_event(ic, CE_CONNECT_ACCEPT, NULL); 1108 1109 mutex_enter(&svc->is_mutex); 1110 } 1111 ksocket_rele(so_svc->is_so); 1112 so_svc->is_thread_running = B_FALSE; 1113 mutex_exit(&svc->is_mutex); 1114 1115 IDM_SVC_LOG(CE_NOTE, "iSCSI service (%p/%d) offline", (void *)svc, 1116 svc->is_svc_req.sr_port); 1117 1118 thread_exit(); 1119 } 1120 1121 /* 1122 * idm_so_free_task_rsrc() stops any ongoing processing of the task and 1123 * frees resources associated with the task. 1124 * 1125 * It's not clear that this should return idm_status_t. What do we do 1126 * if it fails? 1127 */ 1128 static idm_status_t 1129 idm_so_free_task_rsrc(idm_task_t *idt) 1130 { 1131 idm_buf_t *idb; 1132 1133 /* 1134 * There is nothing to cleanup on initiator connections 1135 */ 1136 if (IDM_CONN_ISINI(idt->idt_ic)) 1137 return (IDM_STATUS_SUCCESS); 1138 1139 /* 1140 * If this is a target connection, call idm_buf_rx_from_ini_done for 1141 * any buffer on the "outbufv" list with idb->idb_in_transport==B_TRUE. 1142 * 1143 * In addition, remove any buffers associated with this task from 1144 * the ic_tx_list. We'll do this by walking the idt_inbufv list, but 1145 * items don't actually get removed from that list (and completion 1146 * routines called) until idm_task_cleanup. 1147 */ 1148 mutex_enter(&idt->idt_mutex); 1149 1150 for (idb = list_head(&idt->idt_outbufv); idb != NULL; 1151 idb = list_next(&idt->idt_outbufv, idb)) { 1152 if (idb->idb_in_transport) { 1153 /* 1154 * idm_buf_rx_from_ini_done releases idt->idt_mutex 1155 */ 1156 idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_ABORTED); 1157 mutex_enter(&idt->idt_mutex); 1158 } 1159 } 1160 1161 for (idb = list_head(&idt->idt_inbufv); idb != NULL; 1162 idb = list_next(&idt->idt_inbufv, idb)) { 1163 /* 1164 * We want to remove these items from the tx_list as well, 1165 * but knowing it's in the idt_inbufv list is not a guarantee 1166 * that it's in the tx_list. If it's on the tx list then 1167 * let idm_sotx_thread() clean it up. 1168 */ 1169 if (idb->idb_in_transport && !idb->idb_tx_thread) { 1170 /* 1171 * idm_buf_tx_to_ini_done releases idt->idt_mutex 1172 */ 1173 idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED); 1174 mutex_enter(&idt->idt_mutex); 1175 } 1176 } 1177 1178 mutex_exit(&idt->idt_mutex); 1179 1180 return (IDM_STATUS_SUCCESS); 1181 } 1182 1183 /* 1184 * idm_so_negotiate_key_values() validates the key values for this connection 1185 */ 1186 /* ARGSUSED */ 1187 static kv_status_t 1188 idm_so_negotiate_key_values(idm_conn_t *it, nvlist_t *request_nvl, 1189 nvlist_t *response_nvl, nvlist_t *negotiated_nvl) 1190 { 1191 /* All parameters are negotiated at the iscsit level */ 1192 return (KV_HANDLED); 1193 } 1194 1195 /* 1196 * idm_so_notice_key_values() activates the negotiated key values for 1197 * this connection. 1198 */ 1199 static void 1200 idm_so_notice_key_values(idm_conn_t *it, nvlist_t *negotiated_nvl) 1201 { 1202 char *nvp_name; 1203 nvpair_t *nvp; 1204 nvpair_t *next_nvp; 1205 int nvrc; 1206 idm_status_t idm_status; 1207 const idm_kv_xlate_t *ikvx; 1208 1209 for (nvp = nvlist_next_nvpair(negotiated_nvl, NULL); 1210 nvp != NULL; nvp = next_nvp) { 1211 next_nvp = nvlist_next_nvpair(negotiated_nvl, nvp); 1212 nvp_name = nvpair_name(nvp); 1213 1214 ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name)); 1215 switch (ikvx->ik_key_id) { 1216 case KI_HEADER_DIGEST: 1217 case KI_DATA_DIGEST: 1218 idm_status = idm_so_handle_digest(it, nvp, ikvx); 1219 ASSERT(idm_status == 0); 1220 1221 /* Remove processed item from negotiated_nvl list */ 1222 nvrc = nvlist_remove_all( 1223 negotiated_nvl, ikvx->ik_key_name); 1224 ASSERT(nvrc == 0); 1225 break; 1226 default: 1227 break; 1228 } 1229 } 1230 } 1231 1232 1233 static idm_status_t 1234 idm_so_handle_digest(idm_conn_t *it, nvpair_t *digest_choice, 1235 const idm_kv_xlate_t *ikvx) 1236 { 1237 int nvrc; 1238 char *digest_choice_string; 1239 1240 nvrc = nvpair_value_string(digest_choice, 1241 &digest_choice_string); 1242 ASSERT(nvrc == 0); 1243 if (strcasecmp(digest_choice_string, "crc32c") == 0) { 1244 switch (ikvx->ik_key_id) { 1245 case KI_HEADER_DIGEST: 1246 it->ic_conn_flags |= IDM_CONN_HEADER_DIGEST; 1247 break; 1248 case KI_DATA_DIGEST: 1249 it->ic_conn_flags |= IDM_CONN_DATA_DIGEST; 1250 break; 1251 default: 1252 ASSERT(0); 1253 break; 1254 } 1255 } else if (strcasecmp(digest_choice_string, "none") == 0) { 1256 switch (ikvx->ik_key_id) { 1257 case KI_HEADER_DIGEST: 1258 it->ic_conn_flags &= ~IDM_CONN_HEADER_DIGEST; 1259 break; 1260 case KI_DATA_DIGEST: 1261 it->ic_conn_flags &= ~IDM_CONN_DATA_DIGEST; 1262 break; 1263 default: 1264 ASSERT(0); 1265 break; 1266 } 1267 } else { 1268 ASSERT(0); 1269 } 1270 1271 return (IDM_STATUS_SUCCESS); 1272 } 1273 1274 1275 /* 1276 * idm_so_conn_is_capable() verifies that the passed connection is provided 1277 * for by the sockets interface. 1278 */ 1279 /* ARGSUSED */ 1280 static boolean_t 1281 idm_so_conn_is_capable(idm_conn_req_t *ic, idm_transport_caps_t *caps) 1282 { 1283 return (B_TRUE); 1284 } 1285 1286 /* 1287 * idm_so_rx_datain() validates the Data Sequence number of the PDU. The 1288 * idm_sorecv_scsidata() function invoked earlier actually reads the data 1289 * off the socket into the appropriate buffers. 1290 */ 1291 static void 1292 idm_so_rx_datain(idm_conn_t *ic, idm_pdu_t *pdu) 1293 { 1294 iscsi_data_hdr_t *bhs; 1295 idm_task_t *idt; 1296 idm_buf_t *idb; 1297 uint32_t datasn; 1298 size_t offset; 1299 iscsi_hdr_t *ihp = (iscsi_hdr_t *)pdu->isp_hdr; 1300 iscsi_data_rsp_hdr_t *idrhp = (iscsi_data_rsp_hdr_t *)ihp; 1301 1302 ASSERT(ic != NULL); 1303 ASSERT(pdu != NULL); 1304 1305 bhs = (iscsi_data_hdr_t *)pdu->isp_hdr; 1306 datasn = ntohl(bhs->datasn); 1307 offset = ntohl(bhs->offset); 1308 1309 ASSERT(bhs->opcode == ISCSI_OP_SCSI_DATA_RSP); 1310 1311 /* 1312 * Look up the task corresponding to the initiator task tag 1313 * to get the buffers affiliated with the task. 1314 */ 1315 idt = idm_task_find(ic, bhs->itt, bhs->ttt); 1316 if (idt == NULL) { 1317 IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: failed to find task"); 1318 idm_pdu_rx_protocol_error(ic, pdu); 1319 return; 1320 } 1321 1322 idb = pdu->isp_sorx_buf; 1323 if (idb == NULL) { 1324 IDM_CONN_LOG(CE_WARN, 1325 "idm_so_rx_datain: failed to find buffer"); 1326 idm_task_rele(idt); 1327 idm_pdu_rx_protocol_error(ic, pdu); 1328 return; 1329 } 1330 1331 /* 1332 * DataSN values should be sequential and should not have any gaps or 1333 * repetitions. Check the DataSN with the one stored in the task. 1334 */ 1335 if (datasn == idt->idt_exp_datasn) { 1336 idt->idt_exp_datasn++; /* keep track of DataSN received */ 1337 } else { 1338 IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: datasn out of order"); 1339 idm_task_rele(idt); 1340 idm_pdu_rx_protocol_error(ic, pdu); 1341 return; 1342 } 1343 1344 /* 1345 * PDUs in a sequence should be in continuously increasing 1346 * address offset 1347 */ 1348 if (offset != idb->idb_exp_offset) { 1349 IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: unexpected offset"); 1350 idm_task_rele(idt); 1351 idm_pdu_rx_protocol_error(ic, pdu); 1352 return; 1353 } 1354 /* Expected next relative buffer offset */ 1355 idb->idb_exp_offset += n2h24(bhs->dlength); 1356 idt->idt_rx_bytes += n2h24(bhs->dlength); 1357 1358 idm_task_rele(idt); 1359 1360 /* 1361 * For now call scsi_rsp which will process the data rsp 1362 * Revisit, need to provide an explicit client entry point for 1363 * phase collapse completions. 1364 */ 1365 if (((ihp->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_DATA_RSP) && 1366 (idrhp->flags & ISCSI_FLAG_DATA_STATUS)) { 1367 (*ic->ic_conn_ops.icb_rx_scsi_rsp)(ic, pdu); 1368 } 1369 1370 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS); 1371 } 1372 1373 /* 1374 * The idm_so_rx_dataout() function is used by the iSCSI target to read 1375 * data from the Data-Out PDU sent by the iSCSI initiator. 1376 * 1377 * This function gets the Initiator Task Tag from the PDU BHS and looks up the 1378 * task to get the buffers associated with the PDU. A PDU might span buffers. 1379 * The data is then read into the respective buffer. 1380 */ 1381 static void 1382 idm_so_rx_dataout(idm_conn_t *ic, idm_pdu_t *pdu) 1383 { 1384 1385 iscsi_data_hdr_t *bhs; 1386 idm_task_t *idt; 1387 idm_buf_t *idb; 1388 size_t offset; 1389 1390 ASSERT(ic != NULL); 1391 ASSERT(pdu != NULL); 1392 1393 bhs = (iscsi_data_hdr_t *)pdu->isp_hdr; 1394 offset = ntohl(bhs->offset); 1395 ASSERT(bhs->opcode == ISCSI_OP_SCSI_DATA); 1396 1397 /* 1398 * Look up the task corresponding to the initiator task tag 1399 * to get the buffers affiliated with the task. 1400 */ 1401 idt = idm_task_find(ic, bhs->itt, bhs->ttt); 1402 if (idt == NULL) { 1403 IDM_CONN_LOG(CE_WARN, 1404 "idm_so_rx_dataout: failed to find task"); 1405 idm_pdu_rx_protocol_error(ic, pdu); 1406 return; 1407 } 1408 1409 idb = pdu->isp_sorx_buf; 1410 if (idb == NULL) { 1411 IDM_CONN_LOG(CE_WARN, 1412 "idm_so_rx_dataout: failed to find buffer"); 1413 idm_task_rele(idt); 1414 idm_pdu_rx_protocol_error(ic, pdu); 1415 return; 1416 } 1417 1418 /* Keep track of data transferred - check data offsets */ 1419 if (offset != idb->idb_exp_offset) { 1420 IDM_CONN_LOG(CE_NOTE, "idm_so_rx_dataout: offset out of seq: " 1421 "%ld, %d", offset, idb->idb_exp_offset); 1422 idm_task_rele(idt); 1423 idm_pdu_rx_protocol_error(ic, pdu); 1424 return; 1425 } 1426 /* Expected next relative offset */ 1427 idb->idb_exp_offset += ntoh24(bhs->dlength); 1428 idt->idt_rx_bytes += n2h24(bhs->dlength); 1429 1430 /* 1431 * Call the buffer callback when the transfer is complete 1432 * 1433 * The connection state machine should only abort tasks after 1434 * shutting down the connection so we are assured that there 1435 * won't be a simultaneous attempt to abort this task at the 1436 * same time as we are processing this PDU (due to a connection 1437 * state change). 1438 */ 1439 if (bhs->flags & ISCSI_FLAG_FINAL) { 1440 /* 1441 * We only want to call idm_buf_rx_from_ini_done once 1442 * per transfer. It's possible that this task has 1443 * already been aborted in which case 1444 * idm_so_free_task_rsrc will call idm_buf_rx_from_ini_done 1445 * for each buffer with idb_in_transport==B_TRUE. To 1446 * close this window and ensure that this doesn't happen, 1447 * we'll clear idb->idb_in_transport now while holding 1448 * the task mutex. This is only really an issue for 1449 * SCSI task abort -- if tasks were being aborted because 1450 * of a connection state change the state machine would 1451 * have already stopped the receive thread. 1452 */ 1453 mutex_enter(&idt->idt_mutex); 1454 1455 /* 1456 * Release the task hold here (obtained in idm_task_find) 1457 * because the task may complete synchronously during 1458 * idm_buf_rx_from_ini_done. Since we still have an active 1459 * buffer we know there is at least one additional hold on idt. 1460 */ 1461 idm_task_rele(idt); 1462 1463 /* 1464 * idm_buf_rx_from_ini_done releases idt->idt_mutex 1465 */ 1466 idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_SUCCESS); 1467 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS); 1468 return; 1469 } 1470 1471 idm_task_rele(idt); 1472 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS); 1473 } 1474 1475 /* 1476 * The idm_so_rx_rtt() function is used by the iSCSI initiator to handle 1477 * the R2T PDU sent by the iSCSI target indicating that it is ready to 1478 * accept data. This gets the Initiator Task Tag (itt) from the PDU BHS 1479 * and looks up the task in the task tree using the itt to get the output 1480 * buffers associated the task. The R2T PDU contains the offset of the 1481 * requested data and the data length. This function then constructs a 1482 * sequence of iSCSI PDUs and outputs the requested data. Each Data-Out 1483 * PDU is associated with the R2T by the Target Transfer Tag (ttt). 1484 */ 1485 1486 static void 1487 idm_so_rx_rtt(idm_conn_t *ic, idm_pdu_t *pdu) 1488 { 1489 idm_task_t *idt; 1490 idm_buf_t *idb; 1491 iscsi_rtt_hdr_t *rtt_hdr; 1492 uint32_t data_offset; 1493 uint32_t data_length; 1494 1495 ASSERT(ic != NULL); 1496 ASSERT(pdu != NULL); 1497 1498 rtt_hdr = (iscsi_rtt_hdr_t *)pdu->isp_hdr; 1499 data_offset = ntohl(rtt_hdr->data_offset); 1500 data_length = ntohl(rtt_hdr->data_length); 1501 idt = idm_task_find(ic, rtt_hdr->itt, rtt_hdr->ttt); 1502 1503 if (idt == NULL) { 1504 IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: could not find task"); 1505 idm_pdu_rx_protocol_error(ic, pdu); 1506 return; 1507 } 1508 1509 /* Find the buffer bound to the task by the iSCSI initiator */ 1510 mutex_enter(&idt->idt_mutex); 1511 idb = idm_buf_find(&idt->idt_outbufv, data_offset); 1512 if (idb == NULL) { 1513 mutex_exit(&idt->idt_mutex); 1514 idm_task_rele(idt); 1515 IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: could not find buffer"); 1516 idm_pdu_rx_protocol_error(ic, pdu); 1517 return; 1518 } 1519 1520 /* return buffer contains this data */ 1521 if (data_offset + data_length > idb->idb_buflen) { 1522 /* Overflow */ 1523 mutex_exit(&idt->idt_mutex); 1524 idm_task_rele(idt); 1525 IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: read from outside " 1526 "buffer"); 1527 idm_pdu_rx_protocol_error(ic, pdu); 1528 return; 1529 } 1530 1531 idt->idt_r2t_ttt = rtt_hdr->ttt; 1532 idt->idt_exp_datasn = 0; 1533 1534 idm_so_send_rtt_data(ic, idt, idb, data_offset, 1535 ntohl(rtt_hdr->data_length)); 1536 mutex_exit(&idt->idt_mutex); 1537 1538 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS); 1539 idm_task_rele(idt); 1540 1541 } 1542 1543 idm_status_t 1544 idm_sorecvdata(idm_conn_t *ic, idm_pdu_t *pdu) 1545 { 1546 uint8_t pad[ISCSI_PAD_WORD_LEN]; 1547 int pad_len; 1548 uint32_t data_digest_crc; 1549 uint32_t crc_calculated; 1550 int total_len; 1551 idm_so_conn_t *so_conn; 1552 1553 so_conn = ic->ic_transport_private; 1554 1555 pad_len = ((ISCSI_PAD_WORD_LEN - 1556 (pdu->isp_datalen & (ISCSI_PAD_WORD_LEN - 1))) & 1557 (ISCSI_PAD_WORD_LEN - 1)); 1558 1559 ASSERT(pdu->isp_iovlen < (PDU_MAX_IOVLEN - 2)); /* pad + data digest */ 1560 1561 total_len = pdu->isp_datalen; 1562 1563 if (pad_len) { 1564 pdu->isp_iov[pdu->isp_iovlen].iov_base = (char *)&pad; 1565 pdu->isp_iov[pdu->isp_iovlen].iov_len = pad_len; 1566 total_len += pad_len; 1567 pdu->isp_iovlen++; 1568 } 1569 1570 /* setup data digest */ 1571 if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) != 0) { 1572 pdu->isp_iov[pdu->isp_iovlen].iov_base = 1573 (char *)&data_digest_crc; 1574 pdu->isp_iov[pdu->isp_iovlen].iov_len = 1575 sizeof (data_digest_crc); 1576 total_len += sizeof (data_digest_crc); 1577 pdu->isp_iovlen++; 1578 } 1579 1580 pdu->isp_data = (uint8_t *)(uintptr_t)pdu->isp_iov[0].iov_base; 1581 1582 if (idm_iov_sorecv(so_conn->ic_so, &pdu->isp_iov[0], 1583 pdu->isp_iovlen, total_len) != 0) { 1584 return (IDM_STATUS_IO); 1585 } 1586 1587 if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) != 0) { 1588 crc_calculated = idm_crc32c(pdu->isp_data, 1589 pdu->isp_datalen); 1590 if (pad_len) { 1591 crc_calculated = idm_crc32c_continued((char *)&pad, 1592 pad_len, crc_calculated); 1593 } 1594 if (crc_calculated != data_digest_crc) { 1595 IDM_CONN_LOG(CE_WARN, 1596 "idm_sorecvdata: " 1597 "CRC error: actual 0x%x, calc 0x%x", 1598 data_digest_crc, crc_calculated); 1599 1600 /* Invalid Data Digest */ 1601 return (IDM_STATUS_DATA_DIGEST); 1602 } 1603 } 1604 1605 return (IDM_STATUS_SUCCESS); 1606 } 1607 1608 /* 1609 * idm_sorecv_scsidata() is used to receive scsi data from the socket. The 1610 * Data-type PDU header must be read into the idm_pdu_t structure prior to 1611 * calling this function. 1612 */ 1613 idm_status_t 1614 idm_sorecv_scsidata(idm_conn_t *ic, idm_pdu_t *pdu) 1615 { 1616 iscsi_data_hdr_t *bhs; 1617 idm_task_t *task; 1618 uint32_t offset; 1619 uint8_t opcode; 1620 uint32_t dlength; 1621 list_t *buflst; 1622 uint32_t xfer_bytes; 1623 idm_status_t status; 1624 1625 ASSERT(ic != NULL); 1626 ASSERT(pdu != NULL); 1627 1628 bhs = (iscsi_data_hdr_t *)pdu->isp_hdr; 1629 1630 offset = ntohl(bhs->offset); 1631 opcode = bhs->opcode; 1632 dlength = n2h24(bhs->dlength); 1633 1634 ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) || 1635 (opcode == ISCSI_OP_SCSI_DATA)); 1636 1637 /* 1638 * Successful lookup implicitly gets a "hold" on the task. This 1639 * hold must be released before leaving this function. At one 1640 * point we were caching this task context and retaining the hold 1641 * but it turned out to be very difficult to release the hold properly. 1642 * The task can be aborted and the connection shutdown between this 1643 * call and the subsequent expected call to idm_so_rx_datain/ 1644 * idm_so_rx_dataout (in which case those functions are not called). 1645 * Releasing the hold in the PDU callback doesn't work well either 1646 * because the whole task may be completed by then at which point 1647 * it is too late to release the hold -- for better or worse this 1648 * code doesn't wait on the refcnts during normal operation. 1649 * idm_task_find() is very fast and it is not a huge burden if we 1650 * have to do it twice. 1651 */ 1652 task = idm_task_find(ic, bhs->itt, bhs->ttt); 1653 if (task == NULL) { 1654 IDM_CONN_LOG(CE_WARN, 1655 "idm_sorecv_scsidata: could not find task"); 1656 return (IDM_STATUS_FAIL); 1657 } 1658 1659 mutex_enter(&task->idt_mutex); 1660 buflst = (opcode == ISCSI_OP_SCSI_DATA_RSP) ? 1661 &task->idt_inbufv : &task->idt_outbufv; 1662 pdu->isp_sorx_buf = idm_buf_find(buflst, offset); 1663 mutex_exit(&task->idt_mutex); 1664 1665 if (pdu->isp_sorx_buf == NULL) { 1666 idm_task_rele(task); 1667 IDM_CONN_LOG(CE_WARN, "idm_sorecv_scsidata: could not find " 1668 "buffer for offset %x opcode=%x", 1669 offset, opcode); 1670 return (IDM_STATUS_FAIL); 1671 } 1672 1673 xfer_bytes = idm_fill_iov(pdu, pdu->isp_sorx_buf, offset, dlength); 1674 ASSERT(xfer_bytes != 0); 1675 if (xfer_bytes != dlength) { 1676 idm_task_rele(task); 1677 /* 1678 * Buffer overflow, connection error. The PDU data is still 1679 * sitting in the socket so we can't use the connection 1680 * again until that data is drained. 1681 */ 1682 return (IDM_STATUS_FAIL); 1683 } 1684 1685 status = idm_sorecvdata(ic, pdu); 1686 1687 idm_task_rele(task); 1688 1689 return (status); 1690 } 1691 1692 static uint32_t 1693 idm_fill_iov(idm_pdu_t *pdu, idm_buf_t *idb, uint32_t ro, uint32_t dlength) 1694 { 1695 uint32_t buf_ro = ro - idb->idb_bufoffset; 1696 uint32_t xfer_len = min(dlength, idb->idb_buflen - buf_ro); 1697 1698 ASSERT(ro >= idb->idb_bufoffset); 1699 1700 pdu->isp_iov[pdu->isp_iovlen].iov_base = 1701 (caddr_t)idb->idb_buf + buf_ro; 1702 pdu->isp_iov[pdu->isp_iovlen].iov_len = xfer_len; 1703 pdu->isp_iovlen++; 1704 1705 return (xfer_len); 1706 } 1707 1708 int 1709 idm_sorecv_nonscsidata(idm_conn_t *ic, idm_pdu_t *pdu) 1710 { 1711 pdu->isp_data = kmem_alloc(pdu->isp_datalen, KM_SLEEP); 1712 ASSERT(pdu->isp_data != NULL); 1713 1714 pdu->isp_databuflen = pdu->isp_datalen; 1715 pdu->isp_iov[0].iov_base = (caddr_t)pdu->isp_data; 1716 pdu->isp_iov[0].iov_len = pdu->isp_datalen; 1717 pdu->isp_iovlen = 1; 1718 /* 1719 * Since we are associating a new data buffer with this received 1720 * PDU we need to set a specific callback to free the data 1721 * after the PDU is processed. 1722 */ 1723 pdu->isp_flags |= IDM_PDU_ADDL_DATA; 1724 pdu->isp_callback = idm_sorx_addl_pdu_cb; 1725 1726 return (idm_sorecvdata(ic, pdu)); 1727 } 1728 1729 void 1730 idm_sorx_thread(void *arg) 1731 { 1732 boolean_t conn_failure = B_FALSE; 1733 idm_conn_t *ic = (idm_conn_t *)arg; 1734 idm_so_conn_t *so_conn; 1735 idm_pdu_t *pdu; 1736 idm_status_t rc; 1737 1738 idm_conn_hold(ic); 1739 1740 mutex_enter(&ic->ic_mutex); 1741 1742 so_conn = ic->ic_transport_private; 1743 so_conn->ic_rx_thread_running = B_TRUE; 1744 so_conn->ic_rx_thread_did = so_conn->ic_rx_thread->t_did; 1745 cv_signal(&ic->ic_cv); 1746 1747 while (so_conn->ic_rx_thread_running) { 1748 mutex_exit(&ic->ic_mutex); 1749 1750 /* 1751 * Get PDU with default header size (large enough for 1752 * BHS plus any anticipated AHS). PDU from 1753 * the cache will have all values set correctly 1754 * for sockets RX including callback. 1755 */ 1756 pdu = kmem_cache_alloc(idm.idm_sorx_pdu_cache, KM_SLEEP); 1757 pdu->isp_ic = ic; 1758 pdu->isp_flags = 0; 1759 pdu->isp_transport_hdrlen = 0; 1760 1761 if ((rc = idm_sorecvhdr(ic, pdu)) != 0) { 1762 /* 1763 * Call idm_pdu_complete so that we call the callback 1764 * and ensure any memory allocated in idm_sorecvhdr 1765 * gets freed up. 1766 */ 1767 idm_pdu_complete(pdu, IDM_STATUS_FAIL); 1768 1769 /* 1770 * If ic_rx_thread_running is still set then 1771 * this is some kind of connection problem 1772 * on the socket. In this case we want to 1773 * generate an event. Otherwise some other 1774 * thread closed the socket due to another 1775 * issue in which case we don't need to 1776 * generate an event. 1777 */ 1778 mutex_enter(&ic->ic_mutex); 1779 if (so_conn->ic_rx_thread_running) { 1780 conn_failure = B_TRUE; 1781 so_conn->ic_rx_thread_running = B_FALSE; 1782 } 1783 1784 continue; 1785 } 1786 1787 /* 1788 * Header has been read and validated. Now we need 1789 * to read the PDU data payload (if present). SCSI data 1790 * need to be transferred from the socket directly into 1791 * the associated transfer buffer for the SCSI task. 1792 */ 1793 if (pdu->isp_datalen != 0) { 1794 if ((IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA) || 1795 (IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA_RSP)) { 1796 rc = idm_sorecv_scsidata(ic, pdu); 1797 /* 1798 * All SCSI errors are fatal to the 1799 * connection right now since we have no 1800 * place to put the data. What we need 1801 * is some kind of sink to dispose of unwanted 1802 * SCSI data. For example an invalid task tag 1803 * should not kill the connection (although 1804 * we may want to drop the connection). 1805 */ 1806 } else { 1807 /* 1808 * Not data PDUs so allocate a buffer for the 1809 * data segment and read the remaining data. 1810 */ 1811 rc = idm_sorecv_nonscsidata(ic, pdu); 1812 } 1813 if (rc != 0) { 1814 /* 1815 * Call idm_pdu_complete so that we call the 1816 * callback and ensure any memory allocated 1817 * in idm_sorecvhdr gets freed up. 1818 */ 1819 idm_pdu_complete(pdu, IDM_STATUS_FAIL); 1820 1821 /* 1822 * If ic_rx_thread_running is still set then 1823 * this is some kind of connection problem 1824 * on the socket. In this case we want to 1825 * generate an event. Otherwise some other 1826 * thread closed the socket due to another 1827 * issue in which case we don't need to 1828 * generate an event. 1829 */ 1830 mutex_enter(&ic->ic_mutex); 1831 if (so_conn->ic_rx_thread_running) { 1832 conn_failure = B_TRUE; 1833 so_conn->ic_rx_thread_running = B_FALSE; 1834 } 1835 continue; 1836 } 1837 } 1838 1839 /* 1840 * Process RX PDU 1841 */ 1842 idm_pdu_rx(ic, pdu); 1843 1844 mutex_enter(&ic->ic_mutex); 1845 } 1846 1847 mutex_exit(&ic->ic_mutex); 1848 1849 /* 1850 * If we dropped out of the RX processing loop because of 1851 * a socket problem or other connection failure (including 1852 * digest errors) then we need to generate a state machine 1853 * event to shut the connection down. 1854 * If the state machine is already in, for example, INIT_ERROR, this 1855 * event will get dropped, and the TX thread will never be notified 1856 * to shut down. To be safe, we'll just notify it here. 1857 */ 1858 if (conn_failure) { 1859 if (so_conn->ic_tx_thread_running) { 1860 so_conn->ic_tx_thread_running = B_FALSE; 1861 mutex_enter(&so_conn->ic_tx_mutex); 1862 cv_signal(&so_conn->ic_tx_cv); 1863 mutex_exit(&so_conn->ic_tx_mutex); 1864 } 1865 1866 idm_conn_event(ic, CE_TRANSPORT_FAIL, rc); 1867 } 1868 1869 idm_conn_rele(ic); 1870 1871 thread_exit(); 1872 } 1873 1874 /* 1875 * idm_so_tx 1876 * 1877 * This is the implementation of idm_transport_ops_t's it_tx_pdu entry 1878 * point. By definition, it is supposed to be fast. So, simply queue 1879 * the entry and return. The real work is done by idm_i_so_tx() via 1880 * idm_sotx_thread(). 1881 */ 1882 1883 static void 1884 idm_so_tx(idm_conn_t *ic, idm_pdu_t *pdu) 1885 { 1886 idm_so_conn_t *so_conn = ic->ic_transport_private; 1887 1888 ASSERT(pdu->isp_ic == ic); 1889 mutex_enter(&so_conn->ic_tx_mutex); 1890 1891 if (!so_conn->ic_tx_thread_running) { 1892 mutex_exit(&so_conn->ic_tx_mutex); 1893 idm_pdu_complete(pdu, IDM_STATUS_ABORTED); 1894 return; 1895 } 1896 1897 list_insert_tail(&so_conn->ic_tx_list, (void *)pdu); 1898 cv_signal(&so_conn->ic_tx_cv); 1899 mutex_exit(&so_conn->ic_tx_mutex); 1900 } 1901 1902 static idm_status_t 1903 idm_i_so_tx(idm_pdu_t *pdu) 1904 { 1905 idm_conn_t *ic = pdu->isp_ic; 1906 idm_status_t status = IDM_STATUS_SUCCESS; 1907 uint8_t pad[ISCSI_PAD_WORD_LEN]; 1908 int pad_len; 1909 uint32_t hdr_digest_crc; 1910 uint32_t data_digest_crc = 0; 1911 int total_len = 0; 1912 int iovlen = 0; 1913 struct iovec iov[6]; 1914 idm_so_conn_t *so_conn; 1915 1916 so_conn = ic->ic_transport_private; 1917 1918 /* Setup BHS */ 1919 iov[iovlen].iov_base = (caddr_t)pdu->isp_hdr; 1920 iov[iovlen].iov_len = pdu->isp_hdrlen; 1921 total_len += iov[iovlen].iov_len; 1922 iovlen++; 1923 1924 /* Setup header digest */ 1925 if (((pdu->isp_flags & IDM_PDU_LOGIN_TX) == 0) && 1926 (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST)) { 1927 hdr_digest_crc = idm_crc32c(pdu->isp_hdr, pdu->isp_hdrlen); 1928 1929 iov[iovlen].iov_base = (caddr_t)&hdr_digest_crc; 1930 iov[iovlen].iov_len = sizeof (hdr_digest_crc); 1931 total_len += iov[iovlen].iov_len; 1932 iovlen++; 1933 } 1934 1935 /* Setup the data */ 1936 if (pdu->isp_datalen) { 1937 idm_task_t *idt; 1938 idm_buf_t *idb; 1939 iscsi_data_hdr_t *ihp; 1940 ihp = (iscsi_data_hdr_t *)pdu->isp_hdr; 1941 /* Write of immediate data */ 1942 if (ic->ic_ffp && 1943 (ihp->opcode == ISCSI_OP_SCSI_CMD || 1944 ihp->opcode == ISCSI_OP_SCSI_DATA)) { 1945 idt = idm_task_find(ic, ihp->itt, ihp->ttt); 1946 if (idt) { 1947 mutex_enter(&idt->idt_mutex); 1948 idb = idm_buf_find(&idt->idt_outbufv, 0); 1949 mutex_exit(&idt->idt_mutex); 1950 /* 1951 * If the initiator call to idm_buf_alloc 1952 * failed then we can get to this point 1953 * without a bound buffer. The associated 1954 * connection failure will clean things up 1955 * later. It would be nice to come up with 1956 * a cleaner way to handle this. In 1957 * particular it seems absurd to look up 1958 * the task and the buffer just to update 1959 * this counter. 1960 */ 1961 if (idb) 1962 idb->idb_xfer_len += pdu->isp_datalen; 1963 idm_task_rele(idt); 1964 } 1965 } 1966 1967 iov[iovlen].iov_base = (caddr_t)pdu->isp_data; 1968 iov[iovlen].iov_len = pdu->isp_datalen; 1969 total_len += iov[iovlen].iov_len; 1970 iovlen++; 1971 } 1972 1973 /* Setup the data pad if necessary */ 1974 pad_len = ((ISCSI_PAD_WORD_LEN - 1975 (pdu->isp_datalen & (ISCSI_PAD_WORD_LEN - 1))) & 1976 (ISCSI_PAD_WORD_LEN - 1)); 1977 1978 if (pad_len) { 1979 bzero(pad, sizeof (pad)); 1980 iov[iovlen].iov_base = (void *)&pad; 1981 iov[iovlen].iov_len = pad_len; 1982 total_len += iov[iovlen].iov_len; 1983 iovlen++; 1984 } 1985 1986 /* 1987 * Setup the data digest if enabled. Data-digest is not sent 1988 * for login-phase PDUs. 1989 */ 1990 if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) && 1991 ((pdu->isp_flags & IDM_PDU_LOGIN_TX) == 0) && 1992 (pdu->isp_datalen || pad_len)) { 1993 /* 1994 * RFC3720/10.2.3: A zero-length Data Segment also 1995 * implies a zero-length data digest. 1996 */ 1997 if (pdu->isp_datalen) { 1998 data_digest_crc = idm_crc32c(pdu->isp_data, 1999 pdu->isp_datalen); 2000 } 2001 if (pad_len) { 2002 data_digest_crc = idm_crc32c_continued(&pad, 2003 pad_len, data_digest_crc); 2004 } 2005 2006 iov[iovlen].iov_base = (caddr_t)&data_digest_crc; 2007 iov[iovlen].iov_len = sizeof (data_digest_crc); 2008 total_len += iov[iovlen].iov_len; 2009 iovlen++; 2010 } 2011 2012 /* Transmit the PDU */ 2013 if (idm_iov_sosend(so_conn->ic_so, &iov[0], iovlen, 2014 total_len) != 0) { 2015 /* Set error status */ 2016 IDM_CONN_LOG(CE_WARN, 2017 "idm_so_tx: failed to transmit the PDU, so: %p ic: %p " 2018 "data: %p", (void *) so_conn->ic_so, (void *) ic, 2019 (void *) pdu->isp_data); 2020 status = IDM_STATUS_IO; 2021 } 2022 2023 /* 2024 * Success does not mean that the PDU actually reached the 2025 * remote node since it could get dropped along the way. 2026 */ 2027 idm_pdu_complete(pdu, status); 2028 2029 return (status); 2030 } 2031 2032 /* 2033 * The idm_so_buf_tx_to_ini() is used by the target iSCSI layer to transmit the 2034 * Data-In PDUs using sockets. Based on the negotiated MaxRecvDataSegmentLength, 2035 * the buffer is segmented into a sequence of Data-In PDUs, ordered by DataSN. 2036 * A target can invoke this function multiple times for a single read command 2037 * (identified by the same ITT) to split the input into several sequences. 2038 * 2039 * DataSN starts with 0 for the first data PDU of an input command and advances 2040 * by 1 for each subsequent data PDU. Each sequence will have its own F bit, 2041 * which is set to 1 for the last data PDU of a sequence. 2042 * 2043 * Scope for Prototype build: 2044 * The data PDUs within a sequence will be sent in order with the buffer offset 2045 * in increasing order. i.e. initiator and target must have negotiated the 2046 * "DataPDUInOrder" to "Yes". The order between sequences is not enforced. 2047 * 2048 * Caller holds idt->idt_mutex 2049 */ 2050 static idm_status_t 2051 idm_so_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb) 2052 { 2053 idm_so_conn_t *so_conn = idb->idb_ic->ic_transport_private; 2054 idm_pdu_t tmppdu; 2055 2056 ASSERT(mutex_owned(&idt->idt_mutex)); 2057 2058 /* 2059 * Put the idm_buf_t on the tx queue. It will be transmitted by 2060 * idm_sotx_thread. 2061 */ 2062 mutex_enter(&so_conn->ic_tx_mutex); 2063 2064 if (!so_conn->ic_tx_thread_running) { 2065 mutex_exit(&so_conn->ic_tx_mutex); 2066 /* 2067 * Don't release idt->idt_mutex since we're supposed to hold 2068 * in when calling idm_buf_tx_to_ini_done 2069 */ 2070 idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED); 2071 return (IDM_STATUS_FAIL); 2072 } 2073 2074 /* 2075 * Build a template for the data PDU headers we will use so that 2076 * the SN values will stay consistent with other PDU's we are 2077 * transmitting like R2T and SCSI status. 2078 */ 2079 bzero(&idb->idb_data_hdr_tmpl, sizeof (iscsi_hdr_t)); 2080 tmppdu.isp_hdr = &idb->idb_data_hdr_tmpl; 2081 (*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, &tmppdu, 2082 ISCSI_OP_SCSI_DATA_RSP); 2083 idb->idb_tx_thread = B_TRUE; 2084 list_insert_tail(&so_conn->ic_tx_list, (void *)idb); 2085 cv_signal(&so_conn->ic_tx_cv); 2086 mutex_exit(&so_conn->ic_tx_mutex); 2087 mutex_exit(&idt->idt_mutex); 2088 2089 /* 2090 * Returning success here indicates the transfer was successfully 2091 * dispatched -- it does not mean that the transfer completed 2092 * successfully. 2093 */ 2094 return (IDM_STATUS_SUCCESS); 2095 } 2096 2097 /* 2098 * The idm_so_buf_rx_from_ini() is used by the target iSCSI layer to specify the 2099 * data blocks it is ready to receive from the initiator in response to a WRITE 2100 * SCSI command. The target iSCSI layer passes the information about the desired 2101 * data blocks to the initiator in one R2T PDU. The receiving buffer, the buffer 2102 * offset and datalen are passed via the 'idb' argument. 2103 * 2104 * Scope for Prototype build: 2105 * R2Ts are required for any Data-Out PDU, i.e. initiator and target must have 2106 * negotiated the "InitialR2T" to "Yes". 2107 * 2108 * Caller holds idt->idt_mutex 2109 */ 2110 static idm_status_t 2111 idm_so_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb) 2112 { 2113 idm_pdu_t *pdu; 2114 iscsi_rtt_hdr_t *rtt; 2115 2116 ASSERT(mutex_owned(&idt->idt_mutex)); 2117 2118 pdu = kmem_cache_alloc(idm.idm_sotx_pdu_cache, KM_SLEEP); 2119 pdu->isp_ic = idt->idt_ic; 2120 bzero(pdu->isp_hdr, sizeof (iscsi_rtt_hdr_t)); 2121 2122 /* iSCSI layer fills the TTT, ITT, StatSN, ExpCmdSN, MaxCmdSN */ 2123 (*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, pdu, ISCSI_OP_RTT_RSP); 2124 2125 /* set the rttsn, rtt.flags, rtt.data_offset and rtt.data_length */ 2126 rtt = (iscsi_rtt_hdr_t *)(pdu->isp_hdr); 2127 2128 rtt->opcode = ISCSI_OP_RTT_RSP; 2129 rtt->flags = ISCSI_FLAG_FINAL; 2130 rtt->data_offset = htonl(idb->idb_bufoffset); 2131 rtt->data_length = htonl(idb->idb_xfer_len); 2132 rtt->rttsn = htonl(idt->idt_exp_rttsn++); 2133 2134 /* Keep track of buffer offsets */ 2135 idb->idb_exp_offset = idb->idb_bufoffset; 2136 mutex_exit(&idt->idt_mutex); 2137 2138 /* 2139 * Transmit the PDU. 2140 */ 2141 idm_pdu_tx(pdu); 2142 2143 return (IDM_STATUS_SUCCESS); 2144 } 2145 2146 static idm_status_t 2147 idm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen) 2148 { 2149 idb->idb_buf = kmem_alloc(buflen, KM_NOSLEEP); 2150 if (idb->idb_buf == NULL) { 2151 IDM_CONN_LOG(CE_NOTE, 2152 "idm_so_buf_alloc: failed buffer allocation"); 2153 return (IDM_STATUS_FAIL); 2154 } 2155 return (IDM_STATUS_SUCCESS); 2156 } 2157 2158 /* ARGSUSED */ 2159 static idm_status_t 2160 idm_so_buf_setup(idm_buf_t *idb) 2161 { 2162 /* Ensure bufalloc'd flag is unset */ 2163 idb->idb_bufalloc = B_FALSE; 2164 2165 return (IDM_STATUS_SUCCESS); 2166 } 2167 2168 /* ARGSUSED */ 2169 static void 2170 idm_so_buf_teardown(idm_buf_t *idb) 2171 { 2172 /* nothing to do here */ 2173 } 2174 2175 static void 2176 idm_so_buf_free(idm_buf_t *idb) 2177 { 2178 kmem_free(idb->idb_buf, idb->idb_buflen); 2179 } 2180 2181 static void 2182 idm_so_send_rtt_data(idm_conn_t *ic, idm_task_t *idt, idm_buf_t *idb, 2183 uint32_t offset, uint32_t length) 2184 { 2185 idm_so_conn_t *so_conn = ic->ic_transport_private; 2186 idm_pdu_t tmppdu; 2187 idm_buf_t *rtt_buf; 2188 2189 ASSERT(mutex_owned(&idt->idt_mutex)); 2190 2191 /* 2192 * Allocate a buffer to represent the RTT transfer. We could further 2193 * optimize this by allocating the buffers internally from an rtt 2194 * specific buffer cache since this is socket-specific code but for 2195 * now we will keep it simple. 2196 */ 2197 rtt_buf = idm_buf_alloc(ic, (uint8_t *)idb->idb_buf + offset, length); 2198 if (rtt_buf == NULL) { 2199 /* 2200 * If we're in FFP then the failure was likely a resource 2201 * allocation issue and we should close the connection by 2202 * sending a CE_TRANSPORT_FAIL event. 2203 * 2204 * If we're not in FFP then idm_buf_alloc will always 2205 * fail and the state is transitioning to "complete" anyway 2206 * so we won't bother to send an event. 2207 */ 2208 mutex_enter(&ic->ic_state_mutex); 2209 if (ic->ic_ffp) 2210 idm_conn_event_locked(ic, CE_TRANSPORT_FAIL, 2211 NULL, CT_NONE); 2212 mutex_exit(&ic->ic_state_mutex); 2213 return; 2214 } 2215 2216 rtt_buf->idb_buf_cb = NULL; 2217 rtt_buf->idb_cb_arg = NULL; 2218 rtt_buf->idb_bufoffset = offset; 2219 rtt_buf->idb_xfer_len = length; 2220 rtt_buf->idb_ic = idt->idt_ic; 2221 rtt_buf->idb_task_binding = idt; 2222 2223 /* 2224 * Put the idm_buf_t on the tx queue. It will be transmitted by 2225 * idm_sotx_thread. 2226 */ 2227 mutex_enter(&so_conn->ic_tx_mutex); 2228 2229 if (!so_conn->ic_tx_thread_running) { 2230 idm_buf_free(rtt_buf); 2231 mutex_exit(&so_conn->ic_tx_mutex); 2232 return; 2233 } 2234 2235 /* 2236 * This new buffer represents an additional reference on the task 2237 */ 2238 idm_task_hold(idt); 2239 2240 /* 2241 * Build a template for the data PDU headers we will use so that 2242 * the SN values will stay consistent with other PDU's we are 2243 * transmitting like R2T and SCSI status. 2244 */ 2245 bzero(&rtt_buf->idb_data_hdr_tmpl, sizeof (iscsi_hdr_t)); 2246 tmppdu.isp_hdr = &rtt_buf->idb_data_hdr_tmpl; 2247 (*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, &tmppdu, 2248 ISCSI_OP_SCSI_DATA); 2249 rtt_buf->idb_tx_thread = B_TRUE; 2250 rtt_buf->idb_in_transport = B_TRUE; 2251 list_insert_tail(&so_conn->ic_tx_list, (void *)rtt_buf); 2252 cv_signal(&so_conn->ic_tx_cv); 2253 mutex_exit(&so_conn->ic_tx_mutex); 2254 } 2255 2256 static void 2257 idm_so_send_rtt_data_done(idm_task_t *idt, idm_buf_t *idb) 2258 { 2259 /* 2260 * Don't worry about status -- we assume any error handling 2261 * is performed by the caller (idm_sotx_thread). 2262 */ 2263 idb->idb_in_transport = B_FALSE; 2264 idm_task_rele(idt); 2265 idm_buf_free(idb); 2266 } 2267 2268 static idm_status_t 2269 idm_so_send_buf_region(idm_task_t *idt, idm_buf_t *idb, 2270 uint32_t buf_region_offset, uint32_t buf_region_length) 2271 { 2272 idm_conn_t *ic; 2273 uint32_t max_dataseglen; 2274 size_t remainder, chunk; 2275 uint32_t data_offset = buf_region_offset; 2276 iscsi_data_hdr_t *bhs; 2277 idm_pdu_t *pdu; 2278 idm_status_t tx_status; 2279 2280 ASSERT(mutex_owned(&idt->idt_mutex)); 2281 2282 ic = idt->idt_ic; 2283 2284 max_dataseglen = 8192; /* Need value from login negotiation */ 2285 remainder = buf_region_length; 2286 2287 while (remainder) { 2288 if (idt->idt_state != TASK_ACTIVE) { 2289 ASSERT((idt->idt_state != TASK_IDLE) && 2290 (idt->idt_state != TASK_COMPLETE)); 2291 return (IDM_STATUS_ABORTED); 2292 } 2293 2294 /* check to see if we need to chunk the data */ 2295 if (remainder > max_dataseglen) { 2296 chunk = max_dataseglen; 2297 } else { 2298 chunk = remainder; 2299 } 2300 2301 /* Data PDU headers will always be sizeof (iscsi_hdr_t) */ 2302 pdu = kmem_cache_alloc(idm.idm_sotx_pdu_cache, KM_SLEEP); 2303 pdu->isp_ic = ic; 2304 2305 /* 2306 * We've already built a build a header template 2307 * to use during the transfer. Use this template so that 2308 * the SN values stay consistent with any unrelated PDU's 2309 * being transmitted. 2310 */ 2311 bcopy(&idb->idb_data_hdr_tmpl, pdu->isp_hdr, 2312 sizeof (iscsi_hdr_t)); 2313 2314 /* 2315 * Set DataSN, data offset, and flags in BHS 2316 * For the prototype build, A = 0, S = 0, U = 0 2317 */ 2318 bhs = (iscsi_data_hdr_t *)(pdu->isp_hdr); 2319 2320 bhs->datasn = htonl(idt->idt_exp_datasn++); 2321 2322 hton24(bhs->dlength, chunk); 2323 bhs->offset = htonl(idb->idb_bufoffset + data_offset); 2324 2325 if (chunk == remainder) { 2326 bhs->flags = ISCSI_FLAG_FINAL; /* F bit set to 1 */ 2327 } 2328 2329 /* setup data */ 2330 pdu->isp_data = (uint8_t *)idb->idb_buf + data_offset; 2331 pdu->isp_datalen = (uint_t)chunk; 2332 remainder -= chunk; 2333 data_offset += chunk; 2334 2335 /* 2336 * Now that we're done working with idt_exp_datasn, 2337 * idt->idt_state and idb->idb_bufoffset we can release 2338 * the task lock -- don't want to hold it across the 2339 * call to idm_i_so_tx since we could block. 2340 */ 2341 mutex_exit(&idt->idt_mutex); 2342 2343 /* 2344 * Transmit the PDU. Call the internal routine directly 2345 * as there is already implicit ordering. 2346 */ 2347 if ((tx_status = idm_i_so_tx(pdu)) != IDM_STATUS_SUCCESS) { 2348 mutex_enter(&idt->idt_mutex); 2349 return (tx_status); 2350 } 2351 2352 mutex_enter(&idt->idt_mutex); 2353 idt->idt_tx_bytes += chunk; 2354 } 2355 2356 return (IDM_STATUS_SUCCESS); 2357 } 2358 2359 /* 2360 * TX PDU cache 2361 */ 2362 /* ARGSUSED */ 2363 int 2364 idm_sotx_pdu_constructor(void *hdl, void *arg, int flags) 2365 { 2366 idm_pdu_t *pdu = hdl; 2367 2368 bzero(pdu, sizeof (idm_pdu_t)); 2369 pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */ 2370 pdu->isp_hdrlen = sizeof (iscsi_hdr_t); 2371 pdu->isp_callback = idm_sotx_cache_pdu_cb; 2372 pdu->isp_magic = IDM_PDU_MAGIC; 2373 bzero(pdu->isp_hdr, sizeof (iscsi_hdr_t)); 2374 2375 return (0); 2376 } 2377 2378 /* ARGSUSED */ 2379 void 2380 idm_sotx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status) 2381 { 2382 /* reset values between use */ 2383 pdu->isp_datalen = 0; 2384 2385 kmem_cache_free(idm.idm_sotx_pdu_cache, pdu); 2386 } 2387 2388 /* 2389 * RX PDU cache 2390 */ 2391 /* ARGSUSED */ 2392 int 2393 idm_sorx_pdu_constructor(void *hdl, void *arg, int flags) 2394 { 2395 idm_pdu_t *pdu = hdl; 2396 2397 bzero(pdu, sizeof (idm_pdu_t)); 2398 pdu->isp_magic = IDM_PDU_MAGIC; 2399 pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */ 2400 pdu->isp_callback = idm_sorx_cache_pdu_cb; 2401 2402 return (0); 2403 } 2404 2405 /* ARGSUSED */ 2406 static void 2407 idm_sorx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status) 2408 { 2409 pdu->isp_iovlen = 0; 2410 pdu->isp_sorx_buf = 0; 2411 kmem_cache_free(idm.idm_sorx_pdu_cache, pdu); 2412 } 2413 2414 static void 2415 idm_sorx_addl_pdu_cb(idm_pdu_t *pdu, idm_status_t status) 2416 { 2417 /* 2418 * We had to modify our cached RX PDU with a longer header buffer 2419 * and/or a longer data buffer. Release the new buffers and fix 2420 * the fields back to what we would expect for a cached RX PDU. 2421 */ 2422 if (pdu->isp_flags & IDM_PDU_ADDL_HDR) { 2423 kmem_free(pdu->isp_hdr, pdu->isp_hdrlen); 2424 } 2425 if (pdu->isp_flags & IDM_PDU_ADDL_DATA) { 2426 kmem_free(pdu->isp_data, pdu->isp_datalen); 2427 } 2428 pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); 2429 pdu->isp_hdrlen = sizeof (iscsi_hdr_t); 2430 pdu->isp_data = NULL; 2431 pdu->isp_datalen = 0; 2432 pdu->isp_sorx_buf = 0; 2433 pdu->isp_callback = idm_sorx_cache_pdu_cb; 2434 idm_sorx_cache_pdu_cb(pdu, status); 2435 } 2436 2437 /* 2438 * This thread is only active when I/O is queued for transmit 2439 * because the socket is busy. 2440 */ 2441 void 2442 idm_sotx_thread(void *arg) 2443 { 2444 idm_conn_t *ic = arg; 2445 idm_tx_obj_t *object, *next; 2446 idm_so_conn_t *so_conn; 2447 idm_status_t status = IDM_STATUS_SUCCESS; 2448 2449 idm_conn_hold(ic); 2450 2451 mutex_enter(&ic->ic_mutex); 2452 so_conn = ic->ic_transport_private; 2453 so_conn->ic_tx_thread_running = B_TRUE; 2454 so_conn->ic_tx_thread_did = so_conn->ic_tx_thread->t_did; 2455 cv_signal(&ic->ic_cv); 2456 mutex_exit(&ic->ic_mutex); 2457 2458 mutex_enter(&so_conn->ic_tx_mutex); 2459 2460 while (so_conn->ic_tx_thread_running) { 2461 while (list_is_empty(&so_conn->ic_tx_list)) { 2462 DTRACE_PROBE1(soconn__tx__sleep, idm_conn_t *, ic); 2463 cv_wait(&so_conn->ic_tx_cv, &so_conn->ic_tx_mutex); 2464 DTRACE_PROBE1(soconn__tx__wakeup, idm_conn_t *, ic); 2465 2466 if (!so_conn->ic_tx_thread_running) { 2467 goto tx_bail; 2468 } 2469 } 2470 2471 object = (idm_tx_obj_t *)list_head(&so_conn->ic_tx_list); 2472 list_remove(&so_conn->ic_tx_list, object); 2473 mutex_exit(&so_conn->ic_tx_mutex); 2474 2475 switch (object->idm_tx_obj_magic) { 2476 case IDM_PDU_MAGIC: 2477 DTRACE_PROBE2(soconn__tx__pdu, idm_conn_t *, ic, 2478 idm_pdu_t *, (idm_pdu_t *)object); 2479 2480 status = idm_i_so_tx((idm_pdu_t *)object); 2481 break; 2482 2483 case IDM_BUF_MAGIC: { 2484 idm_buf_t *idb = (idm_buf_t *)object; 2485 idm_task_t *idt = idb->idb_task_binding; 2486 2487 DTRACE_PROBE2(soconn__tx__buf, idm_conn_t *, ic, 2488 idm_buf_t *, idb); 2489 2490 mutex_enter(&idt->idt_mutex); 2491 status = idm_so_send_buf_region(idt, 2492 idb, 0, idb->idb_xfer_len); 2493 2494 /* 2495 * TX thread owns the buffer so we expect it to 2496 * be "in transport" 2497 */ 2498 ASSERT(idb->idb_in_transport); 2499 if (IDM_CONN_ISTGT(ic)) { 2500 /* 2501 * idm_buf_tx_to_ini_done releases 2502 * idt->idt_mutex 2503 */ 2504 idm_buf_tx_to_ini_done(idt, idb, status); 2505 } else { 2506 idm_so_send_rtt_data_done(idt, idb); 2507 mutex_exit(&idt->idt_mutex); 2508 } 2509 break; 2510 } 2511 2512 default: 2513 IDM_CONN_LOG(CE_WARN, "idm_sotx_thread: Unknown magic " 2514 "(0x%08x)", object->idm_tx_obj_magic); 2515 status = IDM_STATUS_FAIL; 2516 } 2517 2518 mutex_enter(&so_conn->ic_tx_mutex); 2519 2520 if (status != IDM_STATUS_SUCCESS) { 2521 so_conn->ic_tx_thread_running = B_FALSE; 2522 idm_conn_event(ic, CE_TRANSPORT_FAIL, status); 2523 } 2524 } 2525 2526 /* 2527 * Before we leave, we need to abort every item remaining in the 2528 * TX list. 2529 */ 2530 2531 tx_bail: 2532 object = (idm_tx_obj_t *)list_head(&so_conn->ic_tx_list); 2533 2534 while (object != NULL) { 2535 next = list_next(&so_conn->ic_tx_list, object); 2536 2537 list_remove(&so_conn->ic_tx_list, object); 2538 switch (object->idm_tx_obj_magic) { 2539 case IDM_PDU_MAGIC: 2540 idm_pdu_complete((idm_pdu_t *)object, 2541 IDM_STATUS_ABORTED); 2542 break; 2543 2544 case IDM_BUF_MAGIC: { 2545 idm_buf_t *idb = (idm_buf_t *)object; 2546 idm_task_t *idt = idb->idb_task_binding; 2547 mutex_exit(&so_conn->ic_tx_mutex); 2548 mutex_enter(&idt->idt_mutex); 2549 /* 2550 * TX thread owns the buffer so we expect it to 2551 * be "in transport" 2552 */ 2553 ASSERT(idb->idb_in_transport); 2554 if (IDM_CONN_ISTGT(ic)) { 2555 /* 2556 * idm_buf_tx_to_ini_done releases 2557 * idt->idt_mutex 2558 */ 2559 idm_buf_tx_to_ini_done(idt, idb, 2560 IDM_STATUS_ABORTED); 2561 } else { 2562 idm_so_send_rtt_data_done(idt, idb); 2563 mutex_exit(&idt->idt_mutex); 2564 } 2565 mutex_enter(&so_conn->ic_tx_mutex); 2566 break; 2567 } 2568 default: 2569 IDM_CONN_LOG(CE_WARN, 2570 "idm_sotx_thread: Unexpected magic " 2571 "(0x%08x)", object->idm_tx_obj_magic); 2572 } 2573 2574 object = next; 2575 } 2576 2577 mutex_exit(&so_conn->ic_tx_mutex); 2578 idm_conn_rele(ic); 2579 thread_exit(); 2580 /*NOTREACHED*/ 2581 } 2582