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