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