Home | History | Annotate | Line # | Download | only in iscsi
iscsi_utils.c revision 1.16
      1 /*	$NetBSD: iscsi_utils.c,v 1.16 2016/06/05 05:41:53 mlelstv Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004,2005,2006,2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Wasabi Systems, Inc.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include "iscsi_globals.h"
     32 
     33 #include <sys/systm.h>
     34 #include <sys/buf.h>
     35 #include <sys/socketvar.h>
     36 #include <sys/bswap.h>
     37 #include <sys/atomic.h>
     38 
     39 
     40 #ifdef ISCSI_DEBUG
     41 
     42 /* debug helper routine */
     43 void
     44 iscsi_hexdump(void *buff, int len)
     45 {
     46 	uint8_t *bp = (uint8_t *) buff;
     47 	int i;
     48 
     49 	while (len > 0) {
     50 		for (i = min(16, len); i > 0; i--)
     51 			printf("%02x ", *bp++);
     52 		printf("\n");
     53 		len -= 16;
     54 	}
     55 }
     56 
     57 #endif
     58 
     59 /*****************************************************************************
     60  * Digest functions
     61  *****************************************************************************/
     62 
     63 /*****************************************************************
     64  *
     65  * CRC LOOKUP TABLE
     66  * ================
     67  * The following CRC lookup table was generated automagically
     68  * by the Rocksoft^tm Model CRC Algorithm Table Generation
     69  * Program V1.0 using the following model parameters:
     70  *
     71  *    Width   : 4 bytes.
     72  *    Poly    : 0x1EDC6F41L
     73  *    Reverse : TRUE.
     74  *
     75  * For more information on the Rocksoft^tm Model CRC Algorithm,
     76  * see the document titled "A Painless Guide to CRC Error
     77  * Detection Algorithms" by Ross Williams
     78  * (ross (at) guest.adelaide.edu.au.). This document is likely to be
     79  * in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft".
     80  *
     81  *****************************************************************/
     82 
     83 STATIC uint32_t crc_table[256] = {
     84 	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
     85 	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
     86 	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
     87 	0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
     88 	0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
     89 	0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
     90 	0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
     91 	0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
     92 	0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
     93 	0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
     94 	0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
     95 	0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
     96 	0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
     97 	0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
     98 	0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
     99 	0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
    100 	0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
    101 	0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
    102 	0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
    103 	0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
    104 	0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
    105 	0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
    106 	0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
    107 	0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
    108 	0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
    109 	0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
    110 	0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
    111 	0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
    112 	0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
    113 	0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
    114 	0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
    115 	0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
    116 	0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
    117 	0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
    118 	0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
    119 	0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
    120 	0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
    121 	0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
    122 	0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
    123 	0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
    124 	0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
    125 	0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
    126 	0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
    127 	0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
    128 	0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
    129 	0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
    130 	0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
    131 	0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
    132 	0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
    133 	0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
    134 	0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
    135 	0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
    136 	0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
    137 	0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
    138 	0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
    139 	0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
    140 	0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
    141 	0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
    142 	0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
    143 	0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
    144 	0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
    145 	0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
    146 	0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
    147 	0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
    148 };
    149 
    150 
    151 /*
    152  * gen_digest:
    153  *    Generate an iSCSI CRC32C digest over the given data.
    154  *
    155  *    Parameters:
    156  *          buff   The data
    157  *          len   The length of the data in bytes
    158  *
    159  *    Returns:    The digest in network byte order
    160  */
    161 
    162 uint32_t
    163 gen_digest(void *buff, int len)
    164 {
    165 	uint8_t *bp = (uint8_t *) buff;
    166 	uint32_t crc = 0xffffffff;
    167 
    168 	while (len--) {
    169 		crc = ((crc >> 8) & 0x00ffffff) ^ crc_table[(crc ^ *bp++) & 0xff];
    170 	}
    171 	return htonl(bswap32(crc ^ 0xffffffff));
    172 }
    173 
    174 
    175 /*
    176  * gen_digest_2:
    177  *    Generate an iSCSI CRC32C digest over the given data, which is split over
    178  *    two buffers.
    179  *
    180  *    Parameters:
    181  *          buf1, buf2  The data
    182  *          len1, len2  The length of the data in bytes
    183  *
    184  *    Returns:    The digest in network byte order
    185  */
    186 
    187 uint32_t
    188 gen_digest_2(void *buf1, int len1, void *buf2, int len2)
    189 {
    190 	uint8_t *bp = (uint8_t *) buf1;
    191 	uint32_t crc = 0xffffffff;
    192 
    193 	while (len1--) {
    194 		crc = ((crc >> 8) & 0x00ffffff) ^ crc_table[(crc ^ *bp++) & 0xff];
    195 	}
    196 	bp = (uint8_t *) buf2;
    197 	while (len2--) {
    198 		crc = ((crc >> 8) & 0x00ffffff) ^ crc_table[(crc ^ *bp++) & 0xff];
    199 	}
    200 	return htonl(bswap32(crc ^ 0xffffffff));
    201 }
    202 
    203 /*****************************************************************************
    204  * CCB management functions
    205  *****************************************************************************/
    206 
    207 /*
    208  * get_ccb:
    209  *    Get a CCB for the SCSI operation, waiting if none is available.
    210  *
    211  *    Parameter:
    212  *       sess     The session containing this CCB
    213  *       waitok   Whether waiting for a CCB is OK
    214  *
    215  *    Returns:    The CCB.
    216  */
    217 
    218 ccb_t *
    219 get_ccb(connection_t *conn, bool waitok)
    220 {
    221 	ccb_t *ccb;
    222 	session_t *sess = conn->session;
    223 
    224 	mutex_enter(&sess->lock);
    225 	do {
    226 		ccb = TAILQ_FIRST(&sess->ccb_pool);
    227 		DEB(100, ("get_ccb: ccb = %p, waitok = %d\n", ccb, waitok));
    228 
    229 		if (ccb != NULL) {
    230 			TAILQ_REMOVE(&sess->ccb_pool, ccb, chain);
    231 		} else {
    232 			if (!waitok || conn->terminating) {
    233 				mutex_exit(&sess->lock);
    234 				return NULL;
    235 			}
    236 			cv_wait(&sess->ccb_cv, &sess->lock);
    237 		}
    238 	} while (ccb == NULL);
    239 	mutex_exit(&sess->lock);
    240 
    241 	ccb->flags = 0;
    242 	ccb->timedout = TOUT_NONE;
    243 	ccb->xs = NULL;
    244 	ccb->temp_data = NULL;
    245 	ccb->text_data = NULL;
    246 	ccb->status = ISCSI_STATUS_SUCCESS;
    247 	ccb->ITT = (ccb->ITT & 0xffffff);
    248 	ccb->disp = CCBDISP_NOWAIT;
    249 	ccb->connection = conn;
    250 	ccb->num_timeouts = 0;
    251 	atomic_inc_uint(&conn->usecount);
    252 
    253 	DEBC(conn, 15, (
    254 		"get_ccb: ccb = %p, usecount = %d\n",
    255 		ccb, conn->usecount));
    256 
    257 	return ccb;
    258 }
    259 
    260 /*
    261  * free_ccb:
    262  *    Put a CCB back onto the free list.
    263  *
    264  *    Parameter:  The CCB.
    265  */
    266 
    267 void
    268 free_ccb(ccb_t *ccb)
    269 {
    270 	session_t *sess = ccb->session;
    271 	pdu_t *pdu;
    272 
    273 	DEBC(ccb->connection, 15, (
    274 		"free_ccb: ccb = %p, usecount = %d\n",
    275 		ccb, ccb->connection->usecount-1));
    276 
    277 	KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    278 	KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    279 
    280 	atomic_dec_uint(&ccb->connection->usecount);
    281 	ccb->connection = NULL;
    282 
    283 	if (ccb->disp > CCBDISP_NOWAIT) {
    284 		DEBOUT(("Freeing CCB with disp %d\n",ccb->disp));
    285 	}
    286 
    287 	ccb->disp = CCBDISP_UNUSED;
    288 
    289 	/* free temporary data */
    290 	if (ccb->temp_data != NULL) {
    291 		free(ccb->temp_data, M_TEMP);
    292 	}
    293 	if (ccb->text_data != NULL) {
    294 		free(ccb->text_data, M_TEMP);
    295 	}
    296 	/* free PDU waiting for ACK */
    297 	if ((pdu = ccb->pdu_waiting) != NULL) {
    298 		ccb->pdu_waiting = NULL;
    299 		free_pdu(pdu);
    300 	}
    301 
    302 	mutex_enter(&sess->lock);
    303 	TAILQ_INSERT_TAIL(&sess->ccb_pool, ccb, chain);
    304 	mutex_exit(&sess->lock);
    305 
    306 	cv_broadcast(&sess->ccb_cv);
    307 }
    308 
    309 /*
    310  *    create_ccbs
    311  *       "Create" the pool of CCBs. This doesn't actually create the CCBs
    312  *       (they are allocated with the session structure), but it links them
    313  *       into the free-list.
    314  *
    315  *    Parameter:  The session owning the CCBs.
    316  */
    317 
    318 void
    319 create_ccbs(session_t *sess)
    320 {
    321 	int i;
    322 	ccb_t *ccb;
    323 	int sid = sess->id << 8;
    324 
    325 	/* Note: CCBs are initialized to 0 with connection structure */
    326 
    327 	for (i = 0, ccb = sess->ccb; i < CCBS_PER_SESSION; i++, ccb++) {
    328 		ccb->ITT = i | sid;
    329 		ccb->session = sess;
    330 
    331 		callout_init(&ccb->timeout, CALLOUT_MPSAFE);
    332 		callout_setfunc(&ccb->timeout, ccb_timeout_co, ccb);
    333 
    334 		DEB(9, ("Create_ccbs: ccb %p itt %x\n", ccb, ccb->ITT));
    335 		TAILQ_INSERT_HEAD(&sess->ccb_pool, ccb, chain);
    336 	}
    337 }
    338 
    339 /*
    340  * suspend_ccb:
    341  *    Put CCB on wait queue
    342  */
    343 void
    344 suspend_ccb(ccb_t *ccb, bool yes)
    345 {
    346 	connection_t *conn;
    347 
    348 	conn = ccb->connection;
    349 	if (yes) {
    350 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    351 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    352 		TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain);
    353 		ccb->flags |= CCBF_WAITQUEUE;
    354 	} else if (ccb->flags & CCBF_WAITQUEUE) {
    355 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    356 		TAILQ_REMOVE(&conn->ccbs_waiting, ccb, chain);
    357 		ccb->flags &= ~CCBF_WAITQUEUE;
    358 	}
    359 }
    360 
    361 /*
    362  * throttle_ccb:
    363  *    Put CCB on throttling queue
    364  */
    365 void
    366 throttle_ccb(ccb_t *ccb, bool yes)
    367 {
    368 	session_t *sess;
    369 
    370 	KASSERT(mutex_owned(&sess->lock));
    371 
    372 	sess = ccb->session;
    373 	if (yes) {
    374 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    375 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    376 		TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain);
    377 		ccb->flags |= CCBF_THROTTLING;
    378 	} else if (ccb->flags & CCBF_THROTTLING) {
    379 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    380 		TAILQ_REMOVE(&sess->ccbs_throttled, ccb, chain);
    381 		ccb->flags &= ~CCBF_THROTTLING;
    382 	}
    383 }
    384 
    385 
    386 /*
    387  * wake_ccb:
    388  *    Wake up (or dispose of) a CCB. Depending on the CCB's disposition,
    389  *    either wake up the requesting thread, signal SCSIPI that we're done,
    390  *    or just free the CCB for CCBDISP_FREE.
    391  *
    392  *    Parameter:  The CCB to handle and the new status of the CCB
    393  */
    394 
    395 void
    396 wake_ccb(ccb_t *ccb, uint32_t status)
    397 {
    398 	ccb_disp_t disp;
    399 	connection_t *conn;
    400 
    401 	conn = ccb->connection;
    402 
    403 #ifdef ISCSI_DEBUG
    404 	DEBC(conn, 9, ("CCB done, ccb = %p, disp = %d\n",
    405 		ccb, ccb->disp));
    406 #endif
    407 
    408 	ccb_timeout_stop(ccb);
    409 
    410 	mutex_enter(&conn->lock);
    411 	disp = ccb->disp;
    412 	if (disp <= CCBDISP_NOWAIT ||
    413 		(disp == CCBDISP_DEFER && conn->state <= ST_WINDING_DOWN)) {
    414 		mutex_exit(&conn->lock);
    415 		return;
    416 	}
    417 
    418 	suspend_ccb(ccb, FALSE);
    419 	throttle_ccb(ccb, FALSE);
    420 
    421 	/* change the disposition so nobody tries this again */
    422 	ccb->disp = CCBDISP_BUSY;
    423 	ccb->status = status;
    424 	mutex_exit(&conn->lock);
    425 
    426 	switch (disp) {
    427 	case CCBDISP_FREE:
    428 		free_ccb(ccb);
    429 		break;
    430 
    431 	case CCBDISP_WAIT:
    432 		cv_broadcast(&conn->ccb_cv);
    433 		break;
    434 
    435 	case CCBDISP_SCSIPI:
    436 		iscsi_done(ccb);
    437 		free_ccb(ccb);
    438 		break;
    439 
    440 	case CCBDISP_DEFER:
    441 		break;
    442 
    443 	default:
    444 		DEBC(conn, 1, ("CCB done, ccb = %p, invalid disposition %d", ccb, disp));
    445 		free_ccb(ccb);
    446 		break;
    447 	}
    448 }
    449 
    450 /*****************************************************************************
    451  * PDU management functions
    452  *****************************************************************************/
    453 
    454 /*
    455  * get_pdu:
    456  *    Get a PDU for the SCSI operation.
    457  *
    458  *    Parameter:
    459  *          conn     The connection this PDU should be associated with
    460  *          waitok   OK to wait for PDU if TRUE
    461  *
    462  *    Returns:    The PDU or NULL if none is available and waitok is FALSE.
    463  */
    464 
    465 pdu_t *
    466 get_pdu(connection_t *conn, bool waitok)
    467 {
    468 	pdu_t *pdu;
    469 
    470 	mutex_enter(&conn->lock);
    471 	do {
    472 		pdu = TAILQ_FIRST(&conn->pdu_pool);
    473 		if (pdu != NULL)
    474 			TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
    475 
    476 		DEB(100, ("get_pdu_c: pdu = %p, waitok = %d\n", pdu, waitok));
    477 
    478 		if (pdu == NULL) {
    479 			if (!waitok || conn->terminating) {
    480 				mutex_exit(&conn->lock);
    481 				return NULL;
    482 			}
    483 			cv_wait(&conn->conn_cv, &conn->lock);
    484 		}
    485 	} while (pdu == NULL);
    486 	mutex_exit(&conn->lock);
    487 
    488 	memset(pdu, 0, sizeof(pdu_t));
    489 	pdu->connection = conn;
    490 	pdu->disp = PDUDISP_FREE;
    491 
    492 	return pdu;
    493 }
    494 
    495 /*
    496  * free_pdu:
    497  *    Put a PDU back onto the free list.
    498  *
    499  *    Parameter:  The PDU.
    500  */
    501 
    502 void
    503 free_pdu(pdu_t *pdu)
    504 {
    505 	connection_t *conn = pdu->connection;
    506 	pdu_disp_t pdisp;
    507 
    508 	KASSERT((pdu->flags & PDUF_INQUEUE) == 0);
    509 
    510 	if (PDUDISP_UNUSED == (pdisp = pdu->disp))
    511 		return;
    512 	pdu->disp = PDUDISP_UNUSED;
    513 
    514 	/* free temporary data in this PDU */
    515 	if (pdu->temp_data)
    516 		free(pdu->temp_data, M_TEMP);
    517 
    518 	mutex_enter(&conn->lock);
    519 	TAILQ_INSERT_TAIL(&conn->pdu_pool, pdu, chain);
    520 	mutex_exit(&conn->lock);
    521 
    522 	cv_broadcast(&conn->conn_cv);
    523 }
    524 
    525 /*
    526  *    create_pdus
    527  *       "Create" the pool of PDUs. This doesn't actually create the PDUs
    528  *       (they are allocated with the connection structure), but it links them
    529  *       into the free-list.
    530  *
    531  *    Parameter:  The connection owning the PDUs.
    532  */
    533 
    534 void
    535 create_pdus(connection_t *conn)
    536 {
    537 	int i;
    538 	pdu_t *pdu;
    539 
    540 	/* Note: PDUs are initialized to 0 with connection structure */
    541 
    542 	for (i = 0, pdu = conn->pdu; i < PDUS_PER_CONNECTION; i++, pdu++) {
    543 		TAILQ_INSERT_HEAD(&conn->pdu_pool, pdu, chain);
    544 	}
    545 }
    546 
    547 
    548 /*****************************************************************************
    549  * Serial Number management functions
    550  *****************************************************************************/
    551 
    552 /*
    553  * init_sernum:
    554  *    Initialize serial number buffer variables.
    555  *
    556  *    Parameter:
    557  *          buff   The serial number buffer.
    558  */
    559 
    560 void
    561 init_sernum(sernum_buffer_t *buff)
    562 {
    563 
    564 	buff->bottom = 0;
    565 	buff->top = 0;
    566 	buff->next_sn = 0;
    567 	buff->ExpSN = 0;
    568 }
    569 
    570 
    571 /*
    572  * add_sernum:
    573  *    Add a received serial number to the buffer.
    574  *    If the serial number is smaller than the expected one, it is ignored.
    575  *    If it is larger, all missing serial numbers are added as well.
    576  *
    577  *    Parameter:
    578  *          buff   The serial number buffer.
    579  *          num   The received serial number
    580  *
    581  *    Returns:
    582  *          0     if the received block is a duplicate
    583  *          1     if the number is the expected one
    584  *          >1    if the numer is > the expected value, in this case the
    585  *                return value is the number of unacknowledged blocks
    586  *          <0    if the buffer is full (i.e. an excessive number of blocks
    587  *                is unacknowledged)
    588  */
    589 
    590 int
    591 add_sernum(sernum_buffer_t *buff, uint32_t num)
    592 {
    593 	int i, t, b;
    594 	uint32_t n;
    595 	int32_t diff;
    596 
    597 	/*
    598 	 * next_sn is the next expected SN, so normally diff should be 1.
    599 	 */
    600 	n = buff->next_sn;
    601 	diff = (num - n) + 1;
    602 
    603 	if (diff <= 0) {
    604 		return 0;				/* ignore if SN is smaller than expected (dup or retransmit) */
    605 	}
    606 
    607 	buff->next_sn = num + 1;
    608 	t = buff->top;
    609 	b = buff->bottom;
    610 
    611 	for (i = 0; i < diff; i++) {
    612 		buff->sernum[t] = n++;
    613 		buff->ack[t] = false;
    614 		t = (t + 1) % SERNUM_BUFFER_LENGTH;
    615 		if (t == b) {
    616 			DEB(1, ("AddSernum: Buffer Full! num %d, diff %d\n", num, diff));
    617 			return -1;
    618 		}
    619 	}
    620 
    621 	buff->top = t;
    622 	DEB(11, ("AddSernum bottom %d [%d], top %d, num %u, diff %d\n",
    623 			 b, buff->sernum[b], buff->top, num, diff));
    624 
    625 	return diff;
    626 }
    627 
    628 
    629 /*
    630  * ack_sernum:
    631  *    Mark a received serial number as acknowledged. This does not necessarily
    632  *    change the associated ExpSN if there are lower serial numbers in the
    633  *    buffer.
    634  *
    635  *    Parameter:
    636  *          buff   The serial number buffer.
    637  *          num   The serial number to acknowledge.
    638  *
    639  *    Returns:    The value of ExpSN.
    640  */
    641 
    642 uint32_t
    643 ack_sernum(sernum_buffer_t *buff, uint32_t num)
    644 {
    645 	int b = buff->bottom;
    646 	int t = buff->top;
    647 
    648 	/* shortcut for most likely case */
    649 	if (t == (b + 1) && num == buff->sernum[b]) {
    650 		/* buffer is now empty, reset top */
    651 		buff->top = b;
    652 	} else if (b != t) {
    653 		for (; b != t; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    654 			if (!sn_a_lt_b(buff->sernum[b], num))
    655 				break;
    656 		}
    657 		if (num == buff->sernum[b]) {
    658 			if (b == buff->bottom)
    659 				buff->bottom = (b + 1) % SERNUM_BUFFER_LENGTH;
    660 			else
    661 				buff->ack[b] = true;
    662 		}
    663 
    664 		for (b = buff->bottom, num = buff->sernum[b] - 1;
    665 			 b != t && buff->ack[b]; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    666 			num = buff->sernum[b];
    667 		}
    668 	}
    669 
    670 	if (!sn_a_lt_b(num, buff->ExpSN))
    671 		buff->ExpSN = num + 1;
    672 
    673 	DEB(11, ("AckSernum bottom %d, top %d, num %d ExpSN %d\n",
    674 			 buff->bottom, buff->top, num, buff->ExpSN));
    675 
    676 	return buff->ExpSN;
    677 }
    678 
    679 /*
    680  * next_sernum:
    681  *   Return the current command serial number of the session
    682  *   and optionally increment it for the next query
    683  */
    684 uint32_t
    685 get_sernum(session_t *sess, bool bump)
    686 {
    687 	uint32_t sn;
    688 
    689 	KASSERT(mutex_owned(&sess->lock));
    690 
    691 	sn = sess->CmdSN;
    692 	if (bump)
    693 		atomic_inc_32(&sess->CmdSN);
    694 	return sn;
    695 }
    696 
    697 /*
    698  * sernum_in_window:
    699  *   Check wether serial number is in send window
    700  *
    701  */
    702 int
    703 sernum_in_window(session_t *sess)
    704 {
    705 
    706 	KASSERT(mutex_owned(&sess->lock));
    707 	return sn_a_le_b(sess->CmdSN, sess->MaxCmdSN);
    708 }
    709 
    710