2 * Copyright (c) 2005-2007 Daniel Braniss <danny@cs.huji.ac.il>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 | $Id: isc_soc.c,v 1.26 2007/05/19 06:09:01 danny Exp danny $
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include "opt_iscsi_initiator.h"
37 #include <sys/param.h>
38 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/ctype.h>
43 #include <sys/errno.h>
44 #include <sys/sysctl.h>
47 #include <sys/socketvar.h>
48 #include <sys/socket.h>
49 #include <sys/protosw.h>
51 #include <sys/ioccom.h>
52 #include <sys/queue.h>
53 #include <sys/kthread.h>
54 #include <sys/syslog.h>
58 #include <dev/iscsi/initiator/iscsi.h>
59 #include <dev/iscsi/initiator/iscsivar.h>
67 | a dummy function for freeing external storage for mbuf
70 nil_fn(void *a, void *b)
73 static int nil_refcnt = 0;
77 isc_sendPDU(isc_session_t *sp, pduq_t *pq)
82 struct mbuf *mh, **mp;
84 struct uio *uio = &pq->uio;
91 bzero(uio, sizeof(struct uio));
92 uio->uio_rw = UIO_WRITE;
93 uio->uio_segflg = UIO_SYSSPACE;
95 uio->uio_iov = iv = pq->iov;
97 iv->iov_base = &pp->ipdu;
98 iv->iov_len = sizeof(union ipdu_u);
99 uio->uio_resid = pq->len;
102 /* mbuf for the iSCSI header */
103 MGETHDR(mh, M_TRYWAIT, MT_DATA);
104 mh->m_len = mh->m_pkthdr.len = sizeof(union ipdu_u);
105 mh->m_pkthdr.rcvif = NULL;
106 MH_ALIGN(mh, sizeof(union ipdu_u));
107 bcopy(&pp->ipdu, mh->m_data, sizeof(union ipdu_u));
109 #endif /* USE_MBUF */
112 pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
115 iv->iov_base = pp->ahs;
116 iv->iov_len = pp->ahs_len;
119 /* Add any AHS to the iSCSI hdr mbuf */
120 /* XXX Assert: (mh->m_pkthdr.len + pp->ahs_len) < MHLEN */
121 bcopy(pp->ahs, (mh->m_data + mh->m_len), pp->ahs_len);
122 mh->m_len += pp->ahs_len;
123 mh->m_pkthdr.len += pp->ahs_len;
124 #endif /* USE_MBUF */
126 pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
129 debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
131 iv->iov_base = &pp->hdr_dig;
132 iv->iov_len = sizeof(int);
135 /* Add header digest to the iSCSI hdr mbuf */
136 /* XXX Assert: (mh->m_pkthdr.len + 4) < MHLEN */
137 bcopy(&pp->hdr_dig, (mh->m_data + mh->m_len), sizeof(int));
138 mh->m_len += sizeof(int);
139 mh->m_pkthdr.len += sizeof(int);
140 #endif /* USE_MBUF */
144 #endif /* USE_MBUF */
147 iv->iov_base = pp->ds;
148 iv->iov_len = pp->ds_len;
149 while(iv->iov_len & 03) // the specs say it must be int alligned
157 while(len & 03) // the specs say it must be int alligned
163 MGET(md, M_TRYWAIT, MT_DATA);
164 md->m_ext.ref_cnt = &nil_refcnt;
165 l = min(MCLBYTES, len);
166 MEXTADD(md, pp->ds + off, l, nil_fn,
167 NULL, 0, EXT_EXTREF);
170 mh->m_pkthdr.len += l;
177 #endif /* USE_MBUF */
183 #endif /* USE_MBUF */
184 pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
186 iv->iov_base = &pp->ds_dig;
187 iv->iov_len = sizeof(int);
190 MGET(me, M_TRYWAIT, MT_DATA);
191 me->m_len = sizeof(int);
192 MH_ALIGN(mh, sizeof(int));
193 bcopy(&pp->ds_dig, me->m_data, sizeof(int));
196 mh->m_pkthdr.len += sizeof(int);
198 #endif /* USE_MBUF */
202 uio->uio_iovcnt = iv - pq->iov;
203 sdebug(5, "opcode=%x iovcnt=%d uio_resid=%d itt=%x",
204 pp->ipdu.bhs.opcode, uio->uio_iovcnt, uio->uio_resid,
205 ntohl(pp->ipdu.bhs.itt));
206 sdebug(5, "sp=%p sp->soc=%p uio=%p sp->td=%p",
207 sp, sp->soc, uio, sp->td);
210 len = uio->uio_resid;
211 error = sosend(sp->soc, NULL, uio, 0, 0, 0, sp->td);
212 if(uio->uio_resid == 0 || error || len == uio->uio_resid) {
214 sdebug(2, "uio->uio_resid=%d uio->uio_iovcnt=%d error=%d len=%d",
215 uio->uio_resid, uio->uio_iovcnt, error, len);
217 error = EAGAIN; // 35
224 sdebug(1, "uio->uio_resid=%d uio->uio_iovcnt=%d",
225 uio->uio_resid, uio->uio_iovcnt);
227 len -= uio->uio_resid;
228 while(uio->uio_iovcnt > 0) {
229 if(iv->iov_len > len) {
230 caddr_t bp = (caddr_t)iv->iov_base;
233 iv->iov_base = (void *)&bp[len];
241 } while(uio->uio_resid);
245 getbintime(&sp->stats.t_sent);
247 if ((error = sosend(sp->soc, NULL, NULL, mh, 0, 0, sp->td)) != 0) {
250 #endif /* USE_MBUF */
256 getbintime(&sp->stats.t_sent);
258 #endif /* USE_MBUF */
262 | wait till a PDU header is received
266 The format of the BHS is:
268 Byte/ 0 | 1 | 2 | 3 |
270 |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
271 +---------------+---------------+---------------+---------------+
272 0|.|I| Opcode |F| Opcode-specific fields |
273 +---------------+---------------+---------------+---------------+
274 4|TotalAHSLength | DataSegmentLength |
275 +---------------+---------------+---------------+---------------+
276 8| LUN or Opcode-specific fields |
279 +---------------+---------------+---------------+---------------+
280 16| Initiator Task Tag |
281 +---------------+---------------+---------------+---------------+
282 20/ Opcode-specific fields /
284 +---------------+---------------+---------------+---------------+
288 so_getbhs(isc_session_t *sp)
290 bhs_t *bhs = &sp->bhs;
291 struct uio *uio = &sp->uio;
292 struct iovec *iov = &sp->iov;
298 iov->iov_len = sizeof(bhs_t);
302 uio->uio_rw = UIO_READ;
303 uio->uio_segflg = UIO_SYSSPACE;
304 uio->uio_td = curthread; // why ...
305 uio->uio_resid = sizeof(bhs_t);
308 error = soreceive(sp->soc, NULL, uio, 0, 0, &flags);
311 debug(2, "error=%d so_error=%d uio->uio_resid=%d iov.iov_len=%zd",
313 sp->soc->so_error, uio->uio_resid, iov->iov_len);
314 if(!error && (uio->uio_resid > 0)) {
315 debug(2, "error=%d so_error=%d uio->uio_resid=%d iov.iov_len=%zd so_state=%x",
317 sp->soc->so_error, uio->uio_resid, iov->iov_len, sp->soc->so_state);
318 error = EAGAIN; // EPIPE;
325 | so_recv gets called when there is at least
326 | an iSCSI header in the queue
329 so_recv(isc_session_t *sp, pduq_t *pq)
331 struct socket *so = sp->soc;
333 struct uio *uio = &pq->uio;
342 | now calculate how much data should be in the buffer
343 | NOTE: digest is not verified/calculated - yet
350 pp->ahs_len = bhs->AHSLength * 4;
357 #if BYTE_ORDER == LITTLE_ENDIAN
358 pp->ds_len = ((n & 0x00ff0000) >> 16)
360 | ((n & 0x000000ff) << 16);
371 if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) {
373 xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d",
374 len, sp->opt.maxRecvDataSegmentLength);
375 // deep trouble here, probably all we can do is
376 // force a disconnect, XXX: check RFC ...
378 "so_recv: impossible PDU length(%ld) from iSCSI %s/%s\n",
379 len, sp->opt.targetAddress, sp->opt.targetName);
382 | XXX: this will realy screwup the stream.
383 | should clear up the buffer till a valid header
384 | is found, or just close connection ...
385 | should read the RFC.
393 uio->uio_resid = len;
394 uio->uio_td = curthread; // why ...
397 error = soreceive(so, NULL, uio, &pq->mp, NULL, &flags);
398 //if(error == EAGAIN)
399 // XXX: this needs work! it hangs iscontrol
400 if(error || uio->uio_resid)
404 sdebug(6, "len=%d] opcode=0x%x ahs_len=0x%x ds_len=0x%x",
405 pq->len, bhs->opcode, pp->ahs_len, pp->ds_len);
407 max = ntohl(bhs->MaxCmdSN);
408 exp = ntohl(bhs->ExpStSN);
411 max > exp - _MAXINCR) {
412 sdebug(2, "bad cmd window size");
413 error = EIO; // XXX: for now;
417 if(SNA_GT(max, sn->maxCmd))
420 if(SNA_GT(exp, sn->expCmd))
423 sp->cws = sn->maxCmd - sn->expCmd + 1;
428 // XXX: need some work here
429 xdebug("have a problem, error=%d", error);
430 pdu_free(sp->isc, pq);
431 if(!error && uio->uio_resid > 0)
436 | wait for something to arrive.
437 | and if the pdu is without errors, process it.
440 so_input(isc_session_t *sp)
447 | first read in the iSCSI header
449 error = so_getbhs(sp);
454 pq = pdu_alloc(sp->isc, 1); // OK to WAIT
455 pq->pdu.ipdu.bhs = sp->bhs;
456 pq->len = sizeof(bhs_t); // so far only the header was read
457 error = so_recv(sp, pq);
459 error += 0x800; // XXX: just to see the error.
461 // XXX: close connection and exit
465 getbintime(&sp->stats.t_recv);
473 | one per active (connected) session.
474 | this thread is responsible for reading
475 | in packets from the target.
480 isc_session_t *sp = (isc_session_t *)vp;
481 struct socket *so = sp->soc;
486 sp->flags |= ISC_CON_RUNNING;
492 while(sp->flags & ISC_CON_RUN) {
494 if(sp->soc == NULL || !(so->so_state & SS_ISCONNECTED)) {
495 debug(2, "sp->soc=%p", sp->soc);
498 error = so_input(sp);
501 mtx_lock(&sp->io_mtx);
502 if(sp->flags & ISC_OWAITING) {
503 sp->flags &= ~ISC_OWAITING;
506 mtx_unlock(&sp->io_mtx);
511 } else if(error == EPIPE)
513 else if(error == EAGAIN) {
514 if(so->so_state & SS_ISCONNECTED)
515 // there seems to be a problem in 6.0 ...
516 tsleep(sp, PRIBIO, "isc_soc", 2*hz);
519 sdebug(2, "terminated, flags=%x so_count=%d so_state=%x error=%d",
520 sp->flags, so->so_count, so->so_state, error);
521 if((sp->proc != NULL) && sp->signal) {
523 psignal(sp->proc, sp->signal);
524 PROC_UNLOCK(sp->proc);
525 sp->flags |= ISC_SIGNALED;
526 sdebug(2, "pid=%d signaled(%d)", sp->proc->p_pid, sp->signal);
529 // we have to do something ourselves
530 // like closing this session ...
533 | we've been terminated
535 // do we need this mutex ...?
536 mtx_lock(&sp->io_mtx);
537 sp->flags &= ~ISC_CON_RUNNING;
540 mtx_unlock(&sp->io_mtx);
546 isc_stop_receiver(isc_session_t *sp)
551 sdebug(4, "sp=%p sp->soc=%p", sp, sp? sp->soc: 0);
552 soshutdown(sp->soc, SHUT_RD);
554 mtx_lock(&sp->io_mtx);
555 sp->flags &= ~ISC_CON_RUN;
556 while(n-- && (sp->flags & ISC_CON_RUNNING)) {
557 sdebug(3, "waiting n=%d... flags=%x", n, sp->flags);
558 msleep(&sp->soc, &sp->io_mtx, PRIBIO, "isc_stpc", 5*hz);
560 mtx_unlock(&sp->io_mtx);
563 fdrop(sp->fp, sp->td);
570 isc_start_receiver(isc_session_t *sp)
574 sp->flags |= ISC_CON_RUN;
575 kthread_create(isc_soc, sp, &sp->soc_proc, 0, 0, "iscsi%d", sp->sid);