xref: /freebsd/sys/dev/iscsi/icl_soft.c (revision c1d255d3)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2012 The FreeBSD Foundation
5  *
6  * This software was developed by Edward Tomasz Napierala under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  */
31 
32 /*
33  * Software implementation of iSCSI Common Layer kobj(9) interface.
34  */
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 #include <sys/param.h>
40 #include <sys/capsicum.h>
41 #include <sys/condvar.h>
42 #include <sys/conf.h>
43 #include <sys/gsb_crc32.h>
44 #include <sys/file.h>
45 #include <sys/kernel.h>
46 #include <sys/kthread.h>
47 #include <sys/lock.h>
48 #include <sys/mbuf.h>
49 #include <sys/mutex.h>
50 #include <sys/module.h>
51 #include <sys/protosw.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
56 #include <sys/sx.h>
57 #include <sys/uio.h>
58 #include <vm/uma.h>
59 #include <netinet/in.h>
60 #include <netinet/tcp.h>
61 
62 #include <dev/iscsi/icl.h>
63 #include <dev/iscsi/iscsi_proto.h>
64 #include <icl_conn_if.h>
65 
66 #define ICL_CONN_STATE_BHS		1
67 #define ICL_CONN_STATE_AHS		2
68 #define ICL_CONN_STATE_HEADER_DIGEST	3
69 #define ICL_CONN_STATE_DATA		4
70 #define ICL_CONN_STATE_DATA_DIGEST	5
71 
72 struct icl_soft_conn {
73 	struct icl_conn	 ic;
74 
75 	/* soft specific stuff goes here. */
76 	STAILQ_HEAD(, icl_pdu) to_send;
77 	struct cv	 send_cv;
78 	struct cv	 receive_cv;
79 	struct icl_pdu	*receive_pdu;
80 	size_t		 receive_len;
81 	int		 receive_state;
82 	bool		 receive_running;
83 	bool		 check_send_space;
84 	bool		 send_running;
85 };
86 
87 struct icl_soft_pdu {
88 	struct icl_pdu	 ip;
89 
90 	/* soft specific stuff goes here. */
91 	u_int		 ref_cnt;
92 	icl_pdu_cb	 cb;
93 	int		 error;
94 };
95 
96 SYSCTL_NODE(_kern_icl, OID_AUTO, soft, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
97     "Software iSCSI");
98 static int coalesce = 1;
99 SYSCTL_INT(_kern_icl_soft, OID_AUTO, coalesce, CTLFLAG_RWTUN,
100     &coalesce, 0, "Try to coalesce PDUs before sending");
101 static int partial_receive_len = 256 * 1024;
102 SYSCTL_INT(_kern_icl_soft, OID_AUTO, partial_receive_len, CTLFLAG_RWTUN,
103     &partial_receive_len, 0, "Minimum read size for partially received "
104     "data segment");
105 static int max_data_segment_length = 256 * 1024;
106 SYSCTL_INT(_kern_icl_soft, OID_AUTO, max_data_segment_length, CTLFLAG_RWTUN,
107     &max_data_segment_length, 0, "Maximum data segment length");
108 static int first_burst_length = 1024 * 1024;
109 SYSCTL_INT(_kern_icl_soft, OID_AUTO, first_burst_length, CTLFLAG_RWTUN,
110     &first_burst_length, 0, "First burst length");
111 static int max_burst_length = 1024 * 1024;
112 SYSCTL_INT(_kern_icl_soft, OID_AUTO, max_burst_length, CTLFLAG_RWTUN,
113     &max_burst_length, 0, "Maximum burst length");
114 static int sendspace = 1536 * 1024;
115 SYSCTL_INT(_kern_icl_soft, OID_AUTO, sendspace, CTLFLAG_RWTUN,
116     &sendspace, 0, "Default send socket buffer size");
117 static int recvspace = 1536 * 1024;
118 SYSCTL_INT(_kern_icl_soft, OID_AUTO, recvspace, CTLFLAG_RWTUN,
119     &recvspace, 0, "Default receive socket buffer size");
120 
121 static MALLOC_DEFINE(M_ICL_SOFT, "icl_soft", "iSCSI software backend");
122 static uma_zone_t icl_soft_pdu_zone;
123 
124 static volatile u_int	icl_ncons;
125 
126 #define ICL_CONN_LOCK(X)		mtx_lock(X->ic_lock)
127 #define ICL_CONN_UNLOCK(X)		mtx_unlock(X->ic_lock)
128 #define ICL_CONN_LOCK_ASSERT(X)		mtx_assert(X->ic_lock, MA_OWNED)
129 #define ICL_CONN_LOCK_ASSERT_NOT(X)	mtx_assert(X->ic_lock, MA_NOTOWNED)
130 
131 STAILQ_HEAD(icl_pdu_stailq, icl_pdu);
132 
133 static icl_conn_new_pdu_t	icl_soft_conn_new_pdu;
134 static icl_conn_pdu_free_t	icl_soft_conn_pdu_free;
135 static icl_conn_pdu_data_segment_length_t
136 				    icl_soft_conn_pdu_data_segment_length;
137 static icl_conn_pdu_append_data_t	icl_soft_conn_pdu_append_data;
138 static icl_conn_pdu_get_data_t	icl_soft_conn_pdu_get_data;
139 static icl_conn_pdu_queue_t	icl_soft_conn_pdu_queue;
140 static icl_conn_pdu_queue_cb_t	icl_soft_conn_pdu_queue_cb;
141 static icl_conn_handoff_t	icl_soft_conn_handoff;
142 static icl_conn_free_t		icl_soft_conn_free;
143 static icl_conn_close_t		icl_soft_conn_close;
144 static icl_conn_task_setup_t	icl_soft_conn_task_setup;
145 static icl_conn_task_done_t	icl_soft_conn_task_done;
146 static icl_conn_transfer_setup_t	icl_soft_conn_transfer_setup;
147 static icl_conn_transfer_done_t	icl_soft_conn_transfer_done;
148 #ifdef ICL_KERNEL_PROXY
149 static icl_conn_connect_t	icl_soft_conn_connect;
150 #endif
151 
152 static kobj_method_t icl_soft_methods[] = {
153 	KOBJMETHOD(icl_conn_new_pdu, icl_soft_conn_new_pdu),
154 	KOBJMETHOD(icl_conn_pdu_free, icl_soft_conn_pdu_free),
155 	KOBJMETHOD(icl_conn_pdu_data_segment_length,
156 	    icl_soft_conn_pdu_data_segment_length),
157 	KOBJMETHOD(icl_conn_pdu_append_data, icl_soft_conn_pdu_append_data),
158 	KOBJMETHOD(icl_conn_pdu_get_data, icl_soft_conn_pdu_get_data),
159 	KOBJMETHOD(icl_conn_pdu_queue, icl_soft_conn_pdu_queue),
160 	KOBJMETHOD(icl_conn_pdu_queue_cb, icl_soft_conn_pdu_queue_cb),
161 	KOBJMETHOD(icl_conn_handoff, icl_soft_conn_handoff),
162 	KOBJMETHOD(icl_conn_free, icl_soft_conn_free),
163 	KOBJMETHOD(icl_conn_close, icl_soft_conn_close),
164 	KOBJMETHOD(icl_conn_task_setup, icl_soft_conn_task_setup),
165 	KOBJMETHOD(icl_conn_task_done, icl_soft_conn_task_done),
166 	KOBJMETHOD(icl_conn_transfer_setup, icl_soft_conn_transfer_setup),
167 	KOBJMETHOD(icl_conn_transfer_done, icl_soft_conn_transfer_done),
168 #ifdef ICL_KERNEL_PROXY
169 	KOBJMETHOD(icl_conn_connect, icl_soft_conn_connect),
170 #endif
171 	{ 0, 0 }
172 };
173 
174 DEFINE_CLASS(icl_soft, icl_soft_methods, sizeof(struct icl_soft_conn));
175 
176 static void
177 icl_conn_fail(struct icl_conn *ic)
178 {
179 	if (ic->ic_socket == NULL)
180 		return;
181 
182 	/*
183 	 * XXX
184 	 */
185 	ic->ic_socket->so_error = EDOOFUS;
186 	(ic->ic_error)(ic);
187 }
188 
189 static void
190 icl_soft_conn_pdu_free(struct icl_conn *ic, struct icl_pdu *ip)
191 {
192 	struct icl_soft_pdu *isp = (struct icl_soft_pdu *)ip;
193 
194 	KASSERT(isp->ref_cnt == 0, ("freeing active PDU"));
195 	m_freem(ip->ip_bhs_mbuf);
196 	m_freem(ip->ip_ahs_mbuf);
197 	m_freem(ip->ip_data_mbuf);
198 	uma_zfree(icl_soft_pdu_zone, isp);
199 #ifdef DIAGNOSTIC
200 	refcount_release(&ic->ic_outstanding_pdus);
201 #endif
202 }
203 
204 static void
205 icl_soft_pdu_call_cb(struct icl_pdu *ip)
206 {
207 	struct icl_soft_pdu *isp = (struct icl_soft_pdu *)ip;
208 
209 	if (isp->cb != NULL)
210 		isp->cb(ip, isp->error);
211 #ifdef DIAGNOSTIC
212 	refcount_release(&ip->ip_conn->ic_outstanding_pdus);
213 #endif
214 	uma_zfree(icl_soft_pdu_zone, isp);
215 }
216 
217 static void
218 icl_soft_pdu_done(struct icl_pdu *ip, int error)
219 {
220 	struct icl_soft_pdu *isp = (struct icl_soft_pdu *)ip;
221 
222 	if (error != 0)
223 		isp->error = error;
224 
225 	m_freem(ip->ip_bhs_mbuf);
226 	ip->ip_bhs_mbuf = NULL;
227 	m_freem(ip->ip_ahs_mbuf);
228 	ip->ip_ahs_mbuf = NULL;
229 	m_freem(ip->ip_data_mbuf);
230 	ip->ip_data_mbuf = NULL;
231 
232 	if (atomic_fetchadd_int(&isp->ref_cnt, -1) == 1)
233 		icl_soft_pdu_call_cb(ip);
234 }
235 
236 static void
237 icl_soft_mbuf_done(struct mbuf *mb)
238 {
239 	struct icl_soft_pdu *isp = (struct icl_soft_pdu *)mb->m_ext.ext_arg1;
240 
241 	icl_soft_pdu_call_cb(&isp->ip);
242 }
243 
244 /*
245  * Allocate icl_pdu with empty BHS to fill up by the caller.
246  */
247 struct icl_pdu *
248 icl_soft_conn_new_pdu(struct icl_conn *ic, int flags)
249 {
250 	struct icl_soft_pdu *isp;
251 	struct icl_pdu *ip;
252 
253 #ifdef DIAGNOSTIC
254 	refcount_acquire(&ic->ic_outstanding_pdus);
255 #endif
256 	isp = uma_zalloc(icl_soft_pdu_zone, flags | M_ZERO);
257 	if (isp == NULL) {
258 		ICL_WARN("failed to allocate soft PDU");
259 #ifdef DIAGNOSTIC
260 		refcount_release(&ic->ic_outstanding_pdus);
261 #endif
262 		return (NULL);
263 	}
264 	ip = &isp->ip;
265 	ip->ip_conn = ic;
266 
267 	CTASSERT(sizeof(struct iscsi_bhs) <= MHLEN);
268 	ip->ip_bhs_mbuf = m_gethdr(flags, MT_DATA);
269 	if (ip->ip_bhs_mbuf == NULL) {
270 		ICL_WARN("failed to allocate BHS mbuf");
271 		icl_soft_conn_pdu_free(ic, ip);
272 		return (NULL);
273 	}
274 	ip->ip_bhs = mtod(ip->ip_bhs_mbuf, struct iscsi_bhs *);
275 	memset(ip->ip_bhs, 0, sizeof(struct iscsi_bhs));
276 	ip->ip_bhs_mbuf->m_len = sizeof(struct iscsi_bhs);
277 
278 	return (ip);
279 }
280 
281 static int
282 icl_pdu_ahs_length(const struct icl_pdu *request)
283 {
284 
285 	return (request->ip_bhs->bhs_total_ahs_len * 4);
286 }
287 
288 static size_t
289 icl_pdu_data_segment_length(const struct icl_pdu *request)
290 {
291 	uint32_t len = 0;
292 
293 	len += request->ip_bhs->bhs_data_segment_len[0];
294 	len <<= 8;
295 	len += request->ip_bhs->bhs_data_segment_len[1];
296 	len <<= 8;
297 	len += request->ip_bhs->bhs_data_segment_len[2];
298 
299 	return (len);
300 }
301 
302 size_t
303 icl_soft_conn_pdu_data_segment_length(struct icl_conn *ic,
304     const struct icl_pdu *request)
305 {
306 
307 	return (icl_pdu_data_segment_length(request));
308 }
309 
310 static void
311 icl_pdu_set_data_segment_length(struct icl_pdu *response, uint32_t len)
312 {
313 
314 	response->ip_bhs->bhs_data_segment_len[2] = len;
315 	response->ip_bhs->bhs_data_segment_len[1] = len >> 8;
316 	response->ip_bhs->bhs_data_segment_len[0] = len >> 16;
317 }
318 
319 static size_t
320 icl_pdu_padding(const struct icl_pdu *ip)
321 {
322 
323 	if ((ip->ip_data_len % 4) != 0)
324 		return (4 - (ip->ip_data_len % 4));
325 
326 	return (0);
327 }
328 
329 static size_t
330 icl_pdu_size(const struct icl_pdu *response)
331 {
332 	size_t len;
333 
334 	KASSERT(response->ip_ahs_len == 0, ("responding with AHS"));
335 
336 	len = sizeof(struct iscsi_bhs) + response->ip_data_len +
337 	    icl_pdu_padding(response);
338 	if (response->ip_conn->ic_header_crc32c)
339 		len += ISCSI_HEADER_DIGEST_SIZE;
340 	if (response->ip_data_len != 0 && response->ip_conn->ic_data_crc32c)
341 		len += ISCSI_DATA_DIGEST_SIZE;
342 
343 	return (len);
344 }
345 
346 static void
347 icl_soft_receive_buf(struct mbuf **r, size_t *rs, void *buf, size_t s)
348 {
349 
350 	m_copydata(*r, 0, s, buf);
351 	m_adj(*r, s);
352 	while ((*r) != NULL && (*r)->m_len == 0)
353 		*r = m_free(*r);
354 	*rs -= s;
355 }
356 
357 static void
358 icl_pdu_receive_ahs(struct icl_pdu *request, struct mbuf **r, size_t *rs)
359 {
360 
361 	request->ip_ahs_len = icl_pdu_ahs_length(request);
362 	if (request->ip_ahs_len == 0)
363 		return;
364 
365 	request->ip_ahs_mbuf = *r;
366 	*r = m_split(request->ip_ahs_mbuf, request->ip_ahs_len, M_WAITOK);
367 	*rs -= request->ip_ahs_len;
368 }
369 
370 static uint32_t
371 icl_mbuf_to_crc32c(const struct mbuf *m0)
372 {
373 	uint32_t digest = 0xffffffff;
374 	const struct mbuf *m;
375 
376 	for (m = m0; m != NULL; m = m->m_next)
377 		digest = calculate_crc32c(digest,
378 		    mtod(m, const void *), m->m_len);
379 
380 	digest = digest ^ 0xffffffff;
381 
382 	return (digest);
383 }
384 
385 static int
386 icl_pdu_check_header_digest(struct icl_pdu *request, struct mbuf **r, size_t *rs)
387 {
388 	uint32_t received_digest, valid_digest;
389 
390 	if (request->ip_conn->ic_header_crc32c == false)
391 		return (0);
392 
393 	CTASSERT(sizeof(received_digest) == ISCSI_HEADER_DIGEST_SIZE);
394 	icl_soft_receive_buf(r, rs, &received_digest, ISCSI_HEADER_DIGEST_SIZE);
395 
396 	/* Temporary attach AHS to BHS to calculate header digest. */
397 	request->ip_bhs_mbuf->m_next = request->ip_ahs_mbuf;
398 	valid_digest = icl_mbuf_to_crc32c(request->ip_bhs_mbuf);
399 	request->ip_bhs_mbuf->m_next = NULL;
400 	if (received_digest != valid_digest) {
401 		ICL_WARN("header digest check failed; got 0x%x, "
402 		    "should be 0x%x", received_digest, valid_digest);
403 		return (-1);
404 	}
405 
406 	return (0);
407 }
408 
409 /*
410  * Return the number of bytes that should be waiting in the receive socket
411  * before icl_pdu_receive_data_segment() gets called.
412  */
413 static size_t
414 icl_pdu_data_segment_receive_len(const struct icl_pdu *request)
415 {
416 	size_t len;
417 
418 	len = icl_pdu_data_segment_length(request);
419 	if (len == 0)
420 		return (0);
421 
422 	/*
423 	 * Account for the parts of data segment already read from
424 	 * the socket buffer.
425 	 */
426 	KASSERT(len > request->ip_data_len, ("len <= request->ip_data_len"));
427 	len -= request->ip_data_len;
428 
429 	/*
430 	 * Don't always wait for the full data segment to be delivered
431 	 * to the socket; this might badly affect performance due to
432 	 * TCP window scaling.
433 	 */
434 	if (len > partial_receive_len) {
435 #if 0
436 		ICL_DEBUG("need %zd bytes of data, limiting to %zd",
437 		    len, partial_receive_len));
438 #endif
439 		len = partial_receive_len;
440 
441 		return (len);
442 	}
443 
444 	/*
445 	 * Account for padding.  Note that due to the way code is written,
446 	 * the icl_pdu_receive_data_segment() must always receive padding
447 	 * along with the last part of data segment, because it would be
448 	 * impossible to tell whether we've already received the full data
449 	 * segment including padding, or without it.
450 	 */
451 	if ((len % 4) != 0)
452 		len += 4 - (len % 4);
453 
454 #if 0
455 	ICL_DEBUG("need %zd bytes of data", len));
456 #endif
457 
458 	return (len);
459 }
460 
461 static int
462 icl_pdu_receive_data_segment(struct icl_pdu *request, struct mbuf **r,
463     size_t *rs, bool *more_neededp)
464 {
465 	struct icl_soft_conn *isc;
466 	size_t len, padding = 0;
467 	struct mbuf *m;
468 
469 	isc = (struct icl_soft_conn *)request->ip_conn;
470 
471 	*more_neededp = false;
472 	isc->receive_len = 0;
473 
474 	len = icl_pdu_data_segment_length(request);
475 	if (len == 0)
476 		return (0);
477 
478 	if ((len % 4) != 0)
479 		padding = 4 - (len % 4);
480 
481 	/*
482 	 * Account for already received parts of data segment.
483 	 */
484 	KASSERT(len > request->ip_data_len, ("len <= request->ip_data_len"));
485 	len -= request->ip_data_len;
486 
487 	if (len + padding > *rs) {
488 		/*
489 		 * Not enough data in the socket buffer.  Receive as much
490 		 * as we can.  Don't receive padding, since, obviously, it's
491 		 * not the end of data segment yet.
492 		 */
493 #if 0
494 		ICL_DEBUG("limited from %zd to %zd",
495 		    len + padding, *rs - padding));
496 #endif
497 		len = *rs - padding;
498 		*more_neededp = true;
499 		padding = 0;
500 	}
501 
502 	/*
503 	 * Must not try to receive padding without at least one byte
504 	 * of actual data segment.
505 	 */
506 	if (len > 0) {
507 		m = *r;
508 		*r = m_split(m, len + padding, M_WAITOK);
509 		*rs -= len + padding;
510 
511 		if (request->ip_data_mbuf == NULL)
512 			request->ip_data_mbuf = m;
513 		else
514 			m_cat(request->ip_data_mbuf, m);
515 
516 		request->ip_data_len += len;
517 	} else
518 		ICL_DEBUG("len 0");
519 
520 	if (*more_neededp)
521 		isc->receive_len = icl_pdu_data_segment_receive_len(request);
522 
523 	return (0);
524 }
525 
526 static int
527 icl_pdu_check_data_digest(struct icl_pdu *request, struct mbuf **r, size_t *rs)
528 {
529 	uint32_t received_digest, valid_digest;
530 
531 	if (request->ip_conn->ic_data_crc32c == false)
532 		return (0);
533 
534 	if (request->ip_data_len == 0)
535 		return (0);
536 
537 	CTASSERT(sizeof(received_digest) == ISCSI_DATA_DIGEST_SIZE);
538 	icl_soft_receive_buf(r, rs, &received_digest, ISCSI_DATA_DIGEST_SIZE);
539 
540 	/*
541 	 * Note that ip_data_mbuf also contains padding; since digest
542 	 * calculation is supposed to include that, we iterate over
543 	 * the entire ip_data_mbuf chain, not just ip_data_len bytes of it.
544 	 */
545 	valid_digest = icl_mbuf_to_crc32c(request->ip_data_mbuf);
546 	if (received_digest != valid_digest) {
547 		ICL_WARN("data digest check failed; got 0x%x, "
548 		    "should be 0x%x", received_digest, valid_digest);
549 		return (-1);
550 	}
551 
552 	return (0);
553 }
554 
555 /*
556  * Somewhat contrary to the name, this attempts to receive only one
557  * "part" of PDU at a time; call it repeatedly until it returns non-NULL.
558  */
559 static struct icl_pdu *
560 icl_conn_receive_pdu(struct icl_soft_conn *isc, struct mbuf **r, size_t *rs)
561 {
562 	struct icl_conn *ic = &isc->ic;
563 	struct icl_pdu *request;
564 	size_t len;
565 	int error = 0;
566 	bool more_needed;
567 
568 	if (isc->receive_state == ICL_CONN_STATE_BHS) {
569 		KASSERT(isc->receive_pdu == NULL,
570 		    ("isc->receive_pdu != NULL"));
571 		request = icl_soft_conn_new_pdu(ic, M_NOWAIT);
572 		if (request == NULL) {
573 			ICL_DEBUG("failed to allocate PDU; "
574 			    "dropping connection");
575 			icl_conn_fail(ic);
576 			return (NULL);
577 		}
578 		isc->receive_pdu = request;
579 	} else {
580 		KASSERT(isc->receive_pdu != NULL,
581 		    ("isc->receive_pdu == NULL"));
582 		request = isc->receive_pdu;
583 	}
584 
585 	switch (isc->receive_state) {
586 	case ICL_CONN_STATE_BHS:
587 		//ICL_DEBUG("receiving BHS");
588 		icl_soft_receive_buf(r, rs, request->ip_bhs,
589 		    sizeof(struct iscsi_bhs));
590 
591 		/*
592 		 * We don't enforce any limit for AHS length;
593 		 * its length is stored in 8 bit field.
594 		 */
595 
596 		len = icl_pdu_data_segment_length(request);
597 		if (len > ic->ic_max_recv_data_segment_length) {
598 			ICL_WARN("received data segment "
599 			    "length %zd is larger than negotiated; "
600 			    "dropping connection", len);
601 			error = EINVAL;
602 			break;
603 		}
604 
605 		isc->receive_state = ICL_CONN_STATE_AHS;
606 		isc->receive_len = icl_pdu_ahs_length(request);
607 		break;
608 
609 	case ICL_CONN_STATE_AHS:
610 		//ICL_DEBUG("receiving AHS");
611 		icl_pdu_receive_ahs(request, r, rs);
612 		isc->receive_state = ICL_CONN_STATE_HEADER_DIGEST;
613 		if (ic->ic_header_crc32c == false)
614 			isc->receive_len = 0;
615 		else
616 			isc->receive_len = ISCSI_HEADER_DIGEST_SIZE;
617 		break;
618 
619 	case ICL_CONN_STATE_HEADER_DIGEST:
620 		//ICL_DEBUG("receiving header digest");
621 		error = icl_pdu_check_header_digest(request, r, rs);
622 		if (error != 0) {
623 			ICL_DEBUG("header digest failed; "
624 			    "dropping connection");
625 			break;
626 		}
627 
628 		isc->receive_state = ICL_CONN_STATE_DATA;
629 		isc->receive_len = icl_pdu_data_segment_receive_len(request);
630 		break;
631 
632 	case ICL_CONN_STATE_DATA:
633 		//ICL_DEBUG("receiving data segment");
634 		error = icl_pdu_receive_data_segment(request, r, rs,
635 		    &more_needed);
636 		if (error != 0) {
637 			ICL_DEBUG("failed to receive data segment;"
638 			    "dropping connection");
639 			break;
640 		}
641 
642 		if (more_needed)
643 			break;
644 
645 		isc->receive_state = ICL_CONN_STATE_DATA_DIGEST;
646 		if (request->ip_data_len == 0 || ic->ic_data_crc32c == false)
647 			isc->receive_len = 0;
648 		else
649 			isc->receive_len = ISCSI_DATA_DIGEST_SIZE;
650 		break;
651 
652 	case ICL_CONN_STATE_DATA_DIGEST:
653 		//ICL_DEBUG("receiving data digest");
654 		error = icl_pdu_check_data_digest(request, r, rs);
655 		if (error != 0) {
656 			ICL_DEBUG("data digest failed; "
657 			    "dropping connection");
658 			break;
659 		}
660 
661 		/*
662 		 * We've received complete PDU; reset the receive state machine
663 		 * and return the PDU.
664 		 */
665 		isc->receive_state = ICL_CONN_STATE_BHS;
666 		isc->receive_len = sizeof(struct iscsi_bhs);
667 		isc->receive_pdu = NULL;
668 		return (request);
669 
670 	default:
671 		panic("invalid receive_state %d\n", isc->receive_state);
672 	}
673 
674 	if (error != 0) {
675 		/*
676 		 * Don't free the PDU; it's pointed to by isc->receive_pdu
677 		 * and will get freed in icl_soft_conn_close().
678 		 */
679 		icl_conn_fail(ic);
680 	}
681 
682 	return (NULL);
683 }
684 
685 static void
686 icl_conn_receive_pdus(struct icl_soft_conn *isc, struct mbuf **r, size_t *rs)
687 {
688 	struct icl_conn *ic = &isc->ic;
689 	struct icl_pdu *response;
690 
691 	for (;;) {
692 		if (ic->ic_disconnecting)
693 			return;
694 
695 		/*
696 		 * Loop until we have a complete PDU or there is not enough
697 		 * data in the socket buffer.
698 		 */
699 		if (*rs < isc->receive_len) {
700 #if 0
701 			ICL_DEBUG("not enough data; have %zd, need %zd",
702 			    *rs, isc->receive_len);
703 #endif
704 			return;
705 		}
706 
707 		response = icl_conn_receive_pdu(isc, r, rs);
708 		if (response == NULL)
709 			continue;
710 
711 		if (response->ip_ahs_len > 0) {
712 			ICL_WARN("received PDU with unsupported "
713 			    "AHS; opcode 0x%x; dropping connection",
714 			    response->ip_bhs->bhs_opcode);
715 			icl_soft_conn_pdu_free(ic, response);
716 			icl_conn_fail(ic);
717 			return;
718 		}
719 
720 		(ic->ic_receive)(response);
721 	}
722 }
723 
724 static void
725 icl_receive_thread(void *arg)
726 {
727 	struct icl_soft_conn *isc = arg;
728 	struct icl_conn *ic = &isc->ic;
729 	size_t available, read = 0;
730 	struct socket *so;
731 	struct mbuf *m, *r = NULL;
732 	struct uio uio;
733 	int error, flags;
734 
735 	so = ic->ic_socket;
736 
737 	for (;;) {
738 		SOCKBUF_LOCK(&so->so_rcv);
739 		if (ic->ic_disconnecting) {
740 			SOCKBUF_UNLOCK(&so->so_rcv);
741 			break;
742 		}
743 
744 		/*
745 		 * Set the low watermark, to be checked by
746 		 * soreadable() in icl_soupcall_receive()
747 		 * to avoid unnecessary wakeups until there
748 		 * is enough data received to read the PDU.
749 		 */
750 		available = sbavail(&so->so_rcv);
751 		if (read + available < isc->receive_len) {
752 			so->so_rcv.sb_lowat = isc->receive_len - read;
753 			cv_wait(&isc->receive_cv, SOCKBUF_MTX(&so->so_rcv));
754 			so->so_rcv.sb_lowat = so->so_rcv.sb_hiwat + 1;
755 			available = sbavail(&so->so_rcv);
756 		}
757 		SOCKBUF_UNLOCK(&so->so_rcv);
758 
759 		if (available == 0) {
760 			if (so->so_error != 0) {
761 				ICL_DEBUG("connection error %d; "
762 				    "dropping connection", so->so_error);
763 				icl_conn_fail(ic);
764 				break;
765 			}
766 			continue;
767 		}
768 
769 		memset(&uio, 0, sizeof(uio));
770 		uio.uio_resid = available;
771 		flags = MSG_DONTWAIT;
772 		error = soreceive(so, NULL, &uio, &m, NULL, &flags);
773 		if (error != 0) {
774 			ICL_DEBUG("soreceive error %d", error);
775 			break;
776 		}
777 		if (uio.uio_resid != 0) {
778 			m_freem(m);
779 			ICL_DEBUG("short read");
780 			break;
781 		}
782 		if (r)
783 			m_cat(r, m);
784 		else
785 			r = m;
786 		read += available;
787 
788 		icl_conn_receive_pdus(isc, &r, &read);
789 	}
790 
791 	if (r)
792 		m_freem(r);
793 
794 	ICL_CONN_LOCK(ic);
795 	isc->receive_running = false;
796 	cv_signal(&isc->send_cv);
797 	ICL_CONN_UNLOCK(ic);
798 	kthread_exit();
799 }
800 
801 static int
802 icl_soupcall_receive(struct socket *so, void *arg, int waitflag)
803 {
804 	struct icl_soft_conn *isc;
805 
806 	if (!soreadable(so))
807 		return (SU_OK);
808 
809 	isc = arg;
810 	cv_signal(&isc->receive_cv);
811 	return (SU_OK);
812 }
813 
814 static int
815 icl_pdu_finalize(struct icl_pdu *request)
816 {
817 	size_t padding, pdu_len;
818 	uint32_t digest, zero = 0;
819 	int ok;
820 	struct icl_conn *ic;
821 
822 	ic = request->ip_conn;
823 
824 	icl_pdu_set_data_segment_length(request, request->ip_data_len);
825 
826 	pdu_len = icl_pdu_size(request);
827 
828 	if (ic->ic_header_crc32c) {
829 		digest = icl_mbuf_to_crc32c(request->ip_bhs_mbuf);
830 		ok = m_append(request->ip_bhs_mbuf, sizeof(digest),
831 		    (void *)&digest);
832 		if (ok != 1) {
833 			ICL_WARN("failed to append header digest");
834 			return (1);
835 		}
836 	}
837 
838 	if (request->ip_data_len != 0) {
839 		padding = icl_pdu_padding(request);
840 		if (padding > 0) {
841 			ok = m_append(request->ip_data_mbuf, padding,
842 			    (void *)&zero);
843 			if (ok != 1) {
844 				ICL_WARN("failed to append padding");
845 				return (1);
846 			}
847 		}
848 
849 		if (ic->ic_data_crc32c) {
850 			digest = icl_mbuf_to_crc32c(request->ip_data_mbuf);
851 
852 			ok = m_append(request->ip_data_mbuf, sizeof(digest),
853 			    (void *)&digest);
854 			if (ok != 1) {
855 				ICL_WARN("failed to append data digest");
856 				return (1);
857 			}
858 		}
859 
860 		m_cat(request->ip_bhs_mbuf, request->ip_data_mbuf);
861 		request->ip_data_mbuf = NULL;
862 	}
863 
864 	request->ip_bhs_mbuf->m_pkthdr.len = pdu_len;
865 
866 	return (0);
867 }
868 
869 static void
870 icl_conn_send_pdus(struct icl_soft_conn *isc, struct icl_pdu_stailq *queue)
871 {
872 	struct icl_conn *ic = &isc->ic;
873 	struct icl_pdu *request, *request2;
874 	struct mbuf *m;
875 	struct socket *so;
876 	long available, size, size2;
877 	int coalesced, error;
878 
879 	ICL_CONN_LOCK_ASSERT_NOT(ic);
880 
881 	so = ic->ic_socket;
882 
883 	SOCKBUF_LOCK(&so->so_snd);
884 	/*
885 	 * Check how much space do we have for transmit.  We can't just
886 	 * call sosend() and retry when we get EWOULDBLOCK or EMSGSIZE,
887 	 * as it always frees the mbuf chain passed to it, even in case
888 	 * of error.
889 	 */
890 	available = sbspace(&so->so_snd);
891 	isc->check_send_space = false;
892 
893 	/*
894 	 * Notify the socket upcall that we don't need wakeups
895 	 * for the time being.
896 	 */
897 	so->so_snd.sb_lowat = so->so_snd.sb_hiwat + 1;
898 	SOCKBUF_UNLOCK(&so->so_snd);
899 
900 	while (!STAILQ_EMPTY(queue)) {
901 		request = STAILQ_FIRST(queue);
902 		size = icl_pdu_size(request);
903 		if (available < size) {
904 			/*
905 			 * Set the low watermark, to be checked by
906 			 * sowriteable() in icl_soupcall_send()
907 			 * to avoid unnecessary wakeups until there
908 			 * is enough space for the PDU to fit.
909 			 */
910 			SOCKBUF_LOCK(&so->so_snd);
911 			available = sbspace(&so->so_snd);
912 			if (available < size) {
913 #if 1
914 				ICL_DEBUG("no space to send; "
915 				    "have %ld, need %ld",
916 				    available, size);
917 #endif
918 				so->so_snd.sb_lowat = max(size,
919 				    so->so_snd.sb_hiwat / 8);
920 				SOCKBUF_UNLOCK(&so->so_snd);
921 				return;
922 			}
923 			SOCKBUF_UNLOCK(&so->so_snd);
924 		}
925 		STAILQ_REMOVE_HEAD(queue, ip_next);
926 		error = icl_pdu_finalize(request);
927 		if (error != 0) {
928 			ICL_DEBUG("failed to finalize PDU; "
929 			    "dropping connection");
930 			icl_soft_pdu_done(request, EIO);
931 			icl_conn_fail(ic);
932 			return;
933 		}
934 		if (coalesce) {
935 			m = request->ip_bhs_mbuf;
936 			for (coalesced = 1; ; coalesced++) {
937 				request2 = STAILQ_FIRST(queue);
938 				if (request2 == NULL)
939 					break;
940 				size2 = icl_pdu_size(request2);
941 				if (available < size + size2)
942 					break;
943 				STAILQ_REMOVE_HEAD(queue, ip_next);
944 				error = icl_pdu_finalize(request2);
945 				if (error != 0) {
946 					ICL_DEBUG("failed to finalize PDU; "
947 					    "dropping connection");
948 					icl_soft_pdu_done(request, EIO);
949 					icl_soft_pdu_done(request2, EIO);
950 					icl_conn_fail(ic);
951 					return;
952 				}
953 				while (m->m_next)
954 					m = m->m_next;
955 				m_cat(m, request2->ip_bhs_mbuf);
956 				request2->ip_bhs_mbuf = NULL;
957 				request->ip_bhs_mbuf->m_pkthdr.len += size2;
958 				size += size2;
959 				icl_soft_pdu_done(request2, 0);
960 			}
961 #if 0
962 			if (coalesced > 1) {
963 				ICL_DEBUG("coalesced %d PDUs into %ld bytes",
964 				    coalesced, size);
965 			}
966 #endif
967 		}
968 		available -= size;
969 		error = sosend(so, NULL, NULL, request->ip_bhs_mbuf,
970 		    NULL, MSG_DONTWAIT, curthread);
971 		request->ip_bhs_mbuf = NULL; /* Sosend consumes the mbuf. */
972 		if (error != 0) {
973 			ICL_DEBUG("failed to send PDU, error %d; "
974 			    "dropping connection", error);
975 			icl_soft_pdu_done(request, error);
976 			icl_conn_fail(ic);
977 			return;
978 		}
979 		icl_soft_pdu_done(request, 0);
980 	}
981 }
982 
983 static void
984 icl_send_thread(void *arg)
985 {
986 	struct icl_soft_conn *isc;
987 	struct icl_conn *ic;
988 	struct icl_pdu_stailq queue;
989 
990 	isc = arg;
991 	ic = &isc->ic;
992 
993 	STAILQ_INIT(&queue);
994 
995 	ICL_CONN_LOCK(ic);
996 	for (;;) {
997 		for (;;) {
998 			/*
999 			 * Populate the local queue from the main one.
1000 			 * This way the icl_conn_send_pdus() can go through
1001 			 * all the queued PDUs without holding any locks.
1002 			 */
1003 			if (STAILQ_EMPTY(&queue) || isc->check_send_space)
1004 				STAILQ_CONCAT(&queue, &isc->to_send);
1005 
1006 			ICL_CONN_UNLOCK(ic);
1007 			icl_conn_send_pdus(isc, &queue);
1008 			ICL_CONN_LOCK(ic);
1009 
1010 			/*
1011 			 * The icl_soupcall_send() was called since the last
1012 			 * call to sbspace(); go around;
1013 			 */
1014 			if (isc->check_send_space)
1015 				continue;
1016 
1017 			/*
1018 			 * Local queue is empty, but we still have PDUs
1019 			 * in the main one; go around.
1020 			 */
1021 			if (STAILQ_EMPTY(&queue) &&
1022 			    !STAILQ_EMPTY(&isc->to_send))
1023 				continue;
1024 
1025 			/*
1026 			 * There might be some stuff in the local queue,
1027 			 * which didn't get sent due to not having enough send
1028 			 * space.  Wait for socket upcall.
1029 			 */
1030 			break;
1031 		}
1032 
1033 		if (ic->ic_disconnecting) {
1034 			//ICL_DEBUG("terminating");
1035 			break;
1036 		}
1037 
1038 		cv_wait(&isc->send_cv, ic->ic_lock);
1039 	}
1040 
1041 	/*
1042 	 * We're exiting; move PDUs back to the main queue, so they can
1043 	 * get freed properly.  At this point ordering doesn't matter.
1044 	 */
1045 	STAILQ_CONCAT(&isc->to_send, &queue);
1046 
1047 	isc->send_running = false;
1048 	cv_signal(&isc->send_cv);
1049 	ICL_CONN_UNLOCK(ic);
1050 	kthread_exit();
1051 }
1052 
1053 static int
1054 icl_soupcall_send(struct socket *so, void *arg, int waitflag)
1055 {
1056 	struct icl_soft_conn *isc;
1057 	struct icl_conn *ic;
1058 
1059 	if (!sowriteable(so))
1060 		return (SU_OK);
1061 
1062 	isc = arg;
1063 	ic = &isc->ic;
1064 
1065 	ICL_CONN_LOCK(ic);
1066 	isc->check_send_space = true;
1067 	ICL_CONN_UNLOCK(ic);
1068 
1069 	cv_signal(&isc->send_cv);
1070 
1071 	return (SU_OK);
1072 }
1073 
1074 static int
1075 icl_soft_conn_pdu_append_data(struct icl_conn *ic, struct icl_pdu *request,
1076     const void *addr, size_t len, int flags)
1077 {
1078 	struct icl_soft_pdu *isp = (struct icl_soft_pdu *)request;
1079 	struct mbuf *mb, *newmb;
1080 	size_t copylen, off = 0;
1081 
1082 	KASSERT(len > 0, ("len == 0"));
1083 
1084 	if (flags & ICL_NOCOPY) {
1085 		newmb = m_get(flags & ~ICL_NOCOPY, MT_DATA);
1086 		if (newmb == NULL) {
1087 			ICL_WARN("failed to allocate mbuf");
1088 			return (ENOMEM);
1089 		}
1090 
1091 		newmb->m_flags |= M_RDONLY;
1092 		m_extaddref(newmb, __DECONST(char *, addr), len, &isp->ref_cnt,
1093 		    icl_soft_mbuf_done, isp, NULL);
1094 		newmb->m_len = len;
1095 	} else {
1096 		newmb = m_getm2(NULL, len, flags, MT_DATA, 0);
1097 		if (newmb == NULL) {
1098 			ICL_WARN("failed to allocate mbuf for %zd bytes", len);
1099 			return (ENOMEM);
1100 		}
1101 
1102 		for (mb = newmb; mb != NULL; mb = mb->m_next) {
1103 			copylen = min(M_TRAILINGSPACE(mb), len - off);
1104 			memcpy(mtod(mb, char *), (const char *)addr + off, copylen);
1105 			mb->m_len = copylen;
1106 			off += copylen;
1107 		}
1108 		KASSERT(off == len, ("%s: off != len", __func__));
1109 	}
1110 
1111 	if (request->ip_data_mbuf == NULL) {
1112 		request->ip_data_mbuf = newmb;
1113 		request->ip_data_len = len;
1114 	} else {
1115 		m_cat(request->ip_data_mbuf, newmb);
1116 		request->ip_data_len += len;
1117 	}
1118 
1119 	return (0);
1120 }
1121 
1122 void
1123 icl_soft_conn_pdu_get_data(struct icl_conn *ic, struct icl_pdu *ip,
1124     size_t off, void *addr, size_t len)
1125 {
1126 
1127 	m_copydata(ip->ip_data_mbuf, off, len, addr);
1128 }
1129 
1130 static void
1131 icl_soft_conn_pdu_queue(struct icl_conn *ic, struct icl_pdu *ip)
1132 {
1133 
1134 	icl_soft_conn_pdu_queue_cb(ic, ip, NULL);
1135 }
1136 
1137 static void
1138 icl_soft_conn_pdu_queue_cb(struct icl_conn *ic, struct icl_pdu *ip,
1139     icl_pdu_cb cb)
1140 {
1141 	struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
1142 	struct icl_soft_pdu *isp = (struct icl_soft_pdu *)ip;
1143 
1144 	ICL_CONN_LOCK_ASSERT(ic);
1145 	isp->ref_cnt++;
1146 	isp->cb = cb;
1147 
1148 	if (ic->ic_disconnecting || ic->ic_socket == NULL) {
1149 		ICL_DEBUG("icl_pdu_queue on closed connection");
1150 		icl_soft_pdu_done(ip, ENOTCONN);
1151 		return;
1152 	}
1153 
1154 	if (!STAILQ_EMPTY(&isc->to_send)) {
1155 		STAILQ_INSERT_TAIL(&isc->to_send, ip, ip_next);
1156 		/*
1157 		 * If the queue is not empty, someone else had already
1158 		 * signaled the send thread; no need to do that again,
1159 		 * just return.
1160 		 */
1161 		return;
1162 	}
1163 
1164 	STAILQ_INSERT_TAIL(&isc->to_send, ip, ip_next);
1165 	cv_signal(&isc->send_cv);
1166 }
1167 
1168 static struct icl_conn *
1169 icl_soft_new_conn(const char *name, struct mtx *lock)
1170 {
1171 	struct icl_soft_conn *isc;
1172 	struct icl_conn *ic;
1173 
1174 	refcount_acquire(&icl_ncons);
1175 
1176 	isc = (struct icl_soft_conn *)kobj_create(&icl_soft_class, M_ICL_SOFT,
1177 	    M_WAITOK | M_ZERO);
1178 
1179 	STAILQ_INIT(&isc->to_send);
1180 	cv_init(&isc->send_cv, "icl_tx");
1181 	cv_init(&isc->receive_cv, "icl_rx");
1182 
1183 	ic = &isc->ic;
1184 	ic->ic_lock = lock;
1185 #ifdef DIAGNOSTIC
1186 	refcount_init(&ic->ic_outstanding_pdus, 0);
1187 #endif
1188 	ic->ic_name = name;
1189 	ic->ic_offload = "None";
1190 	ic->ic_unmapped = false;
1191 
1192 	return (ic);
1193 }
1194 
1195 void
1196 icl_soft_conn_free(struct icl_conn *ic)
1197 {
1198 	struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
1199 
1200 #ifdef DIAGNOSTIC
1201 	KASSERT(ic->ic_outstanding_pdus == 0,
1202 	    ("destroying session with %d outstanding PDUs",
1203 	     ic->ic_outstanding_pdus));
1204 #endif
1205 	cv_destroy(&isc->send_cv);
1206 	cv_destroy(&isc->receive_cv);
1207 	kobj_delete((struct kobj *)isc, M_ICL_SOFT);
1208 	refcount_release(&icl_ncons);
1209 }
1210 
1211 static int
1212 icl_conn_start(struct icl_conn *ic)
1213 {
1214 	struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
1215 	size_t minspace;
1216 	struct sockopt opt;
1217 	int error, one = 1;
1218 
1219 	ICL_CONN_LOCK(ic);
1220 
1221 	/*
1222 	 * XXX: Ugly hack.
1223 	 */
1224 	if (ic->ic_socket == NULL) {
1225 		ICL_CONN_UNLOCK(ic);
1226 		return (EINVAL);
1227 	}
1228 
1229 	isc->receive_state = ICL_CONN_STATE_BHS;
1230 	isc->receive_len = sizeof(struct iscsi_bhs);
1231 	ic->ic_disconnecting = false;
1232 
1233 	ICL_CONN_UNLOCK(ic);
1234 
1235 	/*
1236 	 * For sendspace, this is required because the current code cannot
1237 	 * send a PDU in pieces; thus, the minimum buffer size is equal
1238 	 * to the maximum PDU size.  "+4" is to account for possible padding.
1239 	 */
1240 	minspace = sizeof(struct iscsi_bhs) +
1241 	    ic->ic_max_send_data_segment_length +
1242 	    ISCSI_HEADER_DIGEST_SIZE + ISCSI_DATA_DIGEST_SIZE + 4;
1243 	if (sendspace < minspace) {
1244 		ICL_WARN("kern.icl.sendspace too low; must be at least %zd",
1245 		    minspace);
1246 		sendspace = minspace;
1247 	}
1248 	minspace = sizeof(struct iscsi_bhs) +
1249 	    ic->ic_max_recv_data_segment_length +
1250 	    ISCSI_HEADER_DIGEST_SIZE + ISCSI_DATA_DIGEST_SIZE + 4;
1251 	if (recvspace < minspace) {
1252 		ICL_WARN("kern.icl.recvspace too low; must be at least %zd",
1253 		    minspace);
1254 		recvspace = minspace;
1255 	}
1256 
1257 	error = soreserve(ic->ic_socket, sendspace, recvspace);
1258 	if (error != 0) {
1259 		ICL_WARN("soreserve failed with error %d", error);
1260 		icl_soft_conn_close(ic);
1261 		return (error);
1262 	}
1263 	ic->ic_socket->so_snd.sb_flags |= SB_AUTOSIZE;
1264 	ic->ic_socket->so_rcv.sb_flags |= SB_AUTOSIZE;
1265 
1266 	/*
1267 	 * Disable Nagle.
1268 	 */
1269 	bzero(&opt, sizeof(opt));
1270 	opt.sopt_dir = SOPT_SET;
1271 	opt.sopt_level = IPPROTO_TCP;
1272 	opt.sopt_name = TCP_NODELAY;
1273 	opt.sopt_val = &one;
1274 	opt.sopt_valsize = sizeof(one);
1275 	error = sosetopt(ic->ic_socket, &opt);
1276 	if (error != 0) {
1277 		ICL_WARN("disabling TCP_NODELAY failed with error %d", error);
1278 		icl_soft_conn_close(ic);
1279 		return (error);
1280 	}
1281 
1282 	/*
1283 	 * Register socket upcall, to get notified about incoming PDUs
1284 	 * and free space to send outgoing ones.
1285 	 */
1286 	SOCKBUF_LOCK(&ic->ic_socket->so_snd);
1287 	soupcall_set(ic->ic_socket, SO_SND, icl_soupcall_send, isc);
1288 	SOCKBUF_UNLOCK(&ic->ic_socket->so_snd);
1289 	SOCKBUF_LOCK(&ic->ic_socket->so_rcv);
1290 	soupcall_set(ic->ic_socket, SO_RCV, icl_soupcall_receive, isc);
1291 	SOCKBUF_UNLOCK(&ic->ic_socket->so_rcv);
1292 
1293 	/*
1294 	 * Start threads.
1295 	 */
1296 	ICL_CONN_LOCK(ic);
1297 	isc->send_running = isc->receive_running = true;
1298 	ICL_CONN_UNLOCK(ic);
1299 	error = kthread_add(icl_send_thread, ic, NULL, NULL, 0, 0, "%stx",
1300 	    ic->ic_name);
1301 	if (error != 0) {
1302 		ICL_WARN("kthread_add(9) failed with error %d", error);
1303 		ICL_CONN_LOCK(ic);
1304 		isc->send_running = isc->receive_running = false;
1305 		cv_signal(&isc->send_cv);
1306 		ICL_CONN_UNLOCK(ic);
1307 		icl_soft_conn_close(ic);
1308 		return (error);
1309 	}
1310 	error = kthread_add(icl_receive_thread, ic, NULL, NULL, 0, 0, "%srx",
1311 	    ic->ic_name);
1312 	if (error != 0) {
1313 		ICL_WARN("kthread_add(9) failed with error %d", error);
1314 		ICL_CONN_LOCK(ic);
1315 		isc->receive_running = false;
1316 		cv_signal(&isc->send_cv);
1317 		ICL_CONN_UNLOCK(ic);
1318 		icl_soft_conn_close(ic);
1319 		return (error);
1320 	}
1321 
1322 	return (0);
1323 }
1324 
1325 int
1326 icl_soft_conn_handoff(struct icl_conn *ic, int fd)
1327 {
1328 	struct file *fp;
1329 	struct socket *so;
1330 	cap_rights_t rights;
1331 	int error;
1332 
1333 	ICL_CONN_LOCK_ASSERT_NOT(ic);
1334 
1335 #ifdef ICL_KERNEL_PROXY
1336 	/*
1337 	 * We're transitioning to Full Feature phase, and we don't
1338 	 * really care.
1339 	 */
1340 	if (fd == 0) {
1341 		ICL_CONN_LOCK(ic);
1342 		if (ic->ic_socket == NULL) {
1343 			ICL_CONN_UNLOCK(ic);
1344 			ICL_WARN("proxy handoff without connect");
1345 			return (EINVAL);
1346 		}
1347 		ICL_CONN_UNLOCK(ic);
1348 		return (0);
1349 	}
1350 #endif
1351 
1352 	/*
1353 	 * Steal the socket from userland.
1354 	 */
1355 	error = fget(curthread, fd,
1356 	    cap_rights_init_one(&rights, CAP_SOCK_CLIENT), &fp);
1357 	if (error != 0)
1358 		return (error);
1359 	if (fp->f_type != DTYPE_SOCKET) {
1360 		fdrop(fp, curthread);
1361 		return (EINVAL);
1362 	}
1363 	so = fp->f_data;
1364 	if (so->so_type != SOCK_STREAM) {
1365 		fdrop(fp, curthread);
1366 		return (EINVAL);
1367 	}
1368 
1369 	ICL_CONN_LOCK(ic);
1370 
1371 	if (ic->ic_socket != NULL) {
1372 		ICL_CONN_UNLOCK(ic);
1373 		fdrop(fp, curthread);
1374 		return (EBUSY);
1375 	}
1376 
1377 	ic->ic_socket = fp->f_data;
1378 	fp->f_ops = &badfileops;
1379 	fp->f_data = NULL;
1380 	fdrop(fp, curthread);
1381 	ICL_CONN_UNLOCK(ic);
1382 
1383 	error = icl_conn_start(ic);
1384 
1385 	return (error);
1386 }
1387 
1388 void
1389 icl_soft_conn_close(struct icl_conn *ic)
1390 {
1391 	struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
1392 	struct icl_pdu *pdu;
1393 	struct socket *so;
1394 
1395 	/*
1396 	 * Wake up the threads, so they can properly terminate.
1397 	 * Receive thread sleeps on so->so_rcv lock, send on ic->ic_lock.
1398 	 */
1399 	ICL_CONN_LOCK(ic);
1400 	if (!ic->ic_disconnecting) {
1401 		so = ic->ic_socket;
1402 		if (so)
1403 			SOCKBUF_LOCK(&so->so_rcv);
1404 		ic->ic_disconnecting = true;
1405 		if (so)
1406 			SOCKBUF_UNLOCK(&so->so_rcv);
1407 	}
1408 	while (isc->receive_running || isc->send_running) {
1409 		cv_signal(&isc->receive_cv);
1410 		cv_signal(&isc->send_cv);
1411 		cv_wait(&isc->send_cv, ic->ic_lock);
1412 	}
1413 
1414 	/* Some other thread could close the connection same time. */
1415 	so = ic->ic_socket;
1416 	if (so == NULL) {
1417 		ICL_CONN_UNLOCK(ic);
1418 		return;
1419 	}
1420 	ic->ic_socket = NULL;
1421 
1422 	/*
1423 	 * Deregister socket upcalls.
1424 	 */
1425 	ICL_CONN_UNLOCK(ic);
1426 	SOCKBUF_LOCK(&so->so_snd);
1427 	if (so->so_snd.sb_upcall != NULL)
1428 		soupcall_clear(so, SO_SND);
1429 	SOCKBUF_UNLOCK(&so->so_snd);
1430 	SOCKBUF_LOCK(&so->so_rcv);
1431 	if (so->so_rcv.sb_upcall != NULL)
1432 		soupcall_clear(so, SO_RCV);
1433 	SOCKBUF_UNLOCK(&so->so_rcv);
1434 	soclose(so);
1435 	ICL_CONN_LOCK(ic);
1436 
1437 	if (isc->receive_pdu != NULL) {
1438 		//ICL_DEBUG("freeing partially received PDU");
1439 		icl_soft_conn_pdu_free(ic, isc->receive_pdu);
1440 		isc->receive_pdu = NULL;
1441 	}
1442 
1443 	/*
1444 	 * Remove any outstanding PDUs from the send queue.
1445 	 */
1446 	while (!STAILQ_EMPTY(&isc->to_send)) {
1447 		pdu = STAILQ_FIRST(&isc->to_send);
1448 		STAILQ_REMOVE_HEAD(&isc->to_send, ip_next);
1449 		icl_soft_pdu_done(pdu, ENOTCONN);
1450 	}
1451 
1452 	KASSERT(STAILQ_EMPTY(&isc->to_send),
1453 	    ("destroying session with non-empty send queue"));
1454 	ICL_CONN_UNLOCK(ic);
1455 }
1456 
1457 int
1458 icl_soft_conn_task_setup(struct icl_conn *ic, struct icl_pdu *ip,
1459     struct ccb_scsiio *csio, uint32_t *task_tagp, void **prvp)
1460 {
1461 
1462 	return (0);
1463 }
1464 
1465 void
1466 icl_soft_conn_task_done(struct icl_conn *ic, void *prv)
1467 {
1468 }
1469 
1470 int
1471 icl_soft_conn_transfer_setup(struct icl_conn *ic, union ctl_io *io,
1472     uint32_t *transfer_tag, void **prvp)
1473 {
1474 
1475 	return (0);
1476 }
1477 
1478 void
1479 icl_soft_conn_transfer_done(struct icl_conn *ic, void *prv)
1480 {
1481 }
1482 
1483 static int
1484 icl_soft_limits(struct icl_drv_limits *idl)
1485 {
1486 
1487 	idl->idl_max_recv_data_segment_length = max_data_segment_length;
1488 	idl->idl_max_send_data_segment_length = max_data_segment_length;
1489 	idl->idl_max_burst_length = max_burst_length;
1490 	idl->idl_first_burst_length = first_burst_length;
1491 
1492 	return (0);
1493 }
1494 
1495 #ifdef ICL_KERNEL_PROXY
1496 int
1497 icl_soft_conn_connect(struct icl_conn *ic, int domain, int socktype,
1498     int protocol, struct sockaddr *from_sa, struct sockaddr *to_sa)
1499 {
1500 
1501 	return (icl_soft_proxy_connect(ic, domain, socktype, protocol,
1502 	    from_sa, to_sa));
1503 }
1504 
1505 int
1506 icl_soft_handoff_sock(struct icl_conn *ic, struct socket *so)
1507 {
1508 	int error;
1509 
1510 	ICL_CONN_LOCK_ASSERT_NOT(ic);
1511 
1512 	if (so->so_type != SOCK_STREAM)
1513 		return (EINVAL);
1514 
1515 	ICL_CONN_LOCK(ic);
1516 	if (ic->ic_socket != NULL) {
1517 		ICL_CONN_UNLOCK(ic);
1518 		return (EBUSY);
1519 	}
1520 	ic->ic_socket = so;
1521 	ICL_CONN_UNLOCK(ic);
1522 
1523 	error = icl_conn_start(ic);
1524 
1525 	return (error);
1526 }
1527 #endif /* ICL_KERNEL_PROXY */
1528 
1529 static int
1530 icl_soft_load(void)
1531 {
1532 	int error;
1533 
1534 	icl_soft_pdu_zone = uma_zcreate("icl_soft_pdu",
1535 	    sizeof(struct icl_soft_pdu), NULL, NULL, NULL, NULL,
1536 	    UMA_ALIGN_PTR, 0);
1537 	refcount_init(&icl_ncons, 0);
1538 
1539 	/*
1540 	 * The reason we call this "none" is that to the user,
1541 	 * it's known as "offload driver"; "offload driver: soft"
1542 	 * doesn't make much sense.
1543 	 */
1544 	error = icl_register("none", false, 0,
1545 	    icl_soft_limits, icl_soft_new_conn);
1546 	KASSERT(error == 0, ("failed to register"));
1547 
1548 #if defined(ICL_KERNEL_PROXY) && 0
1549 	/*
1550 	 * Debugging aid for kernel proxy functionality.
1551 	 */
1552 	error = icl_register("proxytest", true, 0,
1553 	    icl_soft_limits, icl_soft_new_conn);
1554 	KASSERT(error == 0, ("failed to register"));
1555 #endif
1556 
1557 	return (error);
1558 }
1559 
1560 static int
1561 icl_soft_unload(void)
1562 {
1563 
1564 	if (icl_ncons != 0)
1565 		return (EBUSY);
1566 
1567 	icl_unregister("none", false);
1568 #if defined(ICL_KERNEL_PROXY) && 0
1569 	icl_unregister("proxytest", true);
1570 #endif
1571 
1572 	uma_zdestroy(icl_soft_pdu_zone);
1573 
1574 	return (0);
1575 }
1576 
1577 static int
1578 icl_soft_modevent(module_t mod, int what, void *arg)
1579 {
1580 
1581 	switch (what) {
1582 	case MOD_LOAD:
1583 		return (icl_soft_load());
1584 	case MOD_UNLOAD:
1585 		return (icl_soft_unload());
1586 	default:
1587 		return (EINVAL);
1588 	}
1589 }
1590 
1591 moduledata_t icl_soft_data = {
1592 	"icl_soft",
1593 	icl_soft_modevent,
1594 	0
1595 };
1596 
1597 DECLARE_MODULE(icl_soft, icl_soft_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
1598 MODULE_DEPEND(icl_soft, icl, 1, 1, 1);
1599 MODULE_VERSION(icl_soft, 1);
1600