Home | History | Annotate | Line # | Download | only in iscsi
iscsi_utils.c revision 1.11
      1 /*	$NetBSD: iscsi_utils.c,v 1.11 2016/06/01 05:13:07 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->xs = NULL;
    243 	ccb->temp_data = NULL;
    244 	ccb->text_data = NULL;
    245 	ccb->status = ISCSI_STATUS_SUCCESS;
    246 	ccb->ITT = (ccb->ITT & 0xffffff) | (++sess->itt_id << 24);
    247 	ccb->disp = CCBDISP_NOWAIT;
    248 	ccb->connection = conn;
    249 	atomic_inc_uint(&conn->usecount);
    250 
    251 	DEBC(conn, 5, (
    252 		"get_ccb: ccb = %p, usecount = %d\n",
    253 		ccb, conn->usecount));
    254 
    255 	return ccb;
    256 }
    257 
    258 /*
    259  * free_ccb:
    260  *    Put a CCB back onto the free list.
    261  *
    262  *    Parameter:  The CCB.
    263  */
    264 
    265 void
    266 free_ccb(ccb_t *ccb)
    267 {
    268 	session_t *sess = ccb->session;
    269 	pdu_t *pdu;
    270 
    271 	DEBC(ccb->connection, 5, (
    272 		"free_ccb: ccb = %p, usecount = %d\n",
    273 		ccb, ccb->connection->usecount-1));
    274 
    275 	KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    276 	KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    277 
    278 	atomic_dec_uint(&ccb->connection->usecount);
    279 	ccb->connection = NULL;
    280 
    281 	if (ccb->disp > CCBDISP_NOWAIT) {
    282 		DEBOUT(("Freeing CCB with disp %d\n",ccb->disp));
    283 	}
    284 
    285 	ccb->disp = CCBDISP_UNUSED;
    286 
    287 	/* free temporary data */
    288 	if (ccb->temp_data != NULL) {
    289 		free(ccb->temp_data, M_TEMP);
    290 	}
    291 	if (ccb->text_data != NULL) {
    292 		free(ccb->text_data, M_TEMP);
    293 	}
    294 	/* free PDU waiting for ACK */
    295 	if ((pdu = ccb->pdu_waiting) != NULL) {
    296 		ccb->pdu_waiting = NULL;
    297 		free_pdu(pdu);
    298 	}
    299 
    300 	mutex_enter(&sess->lock);
    301 	TAILQ_INSERT_TAIL(&sess->ccb_pool, ccb, chain);
    302 	mutex_exit(&sess->lock);
    303 
    304 	cv_broadcast(&sess->ccb_cv);
    305 }
    306 
    307 /*
    308  *    create_ccbs
    309  *       "Create" the pool of CCBs. This doesn't actually create the CCBs
    310  *       (they are allocated with the session structure), but it links them
    311  *       into the free-list.
    312  *
    313  *    Parameter:  The session owning the CCBs.
    314  */
    315 
    316 void
    317 create_ccbs(session_t *sess)
    318 {
    319 	int i;
    320 	ccb_t *ccb;
    321 	int sid = sess->id << 8;
    322 
    323 	/* Note: CCBs are initialized to 0 with connection structure */
    324 
    325 	for (i = 0, ccb = sess->ccb; i < CCBS_PER_SESSION; i++, ccb++) {
    326 		ccb->ITT = i | sid;
    327 		ccb->session = sess;
    328 
    329 		callout_init(&ccb->timeout, CALLOUT_MPSAFE);
    330 		callout_setfunc(&ccb->timeout, ccb_timeout_co, ccb);
    331 
    332 		DEB(9, ("Create_ccbs: ccb %p itt %x\n", ccb, ccb->ITT));
    333 		TAILQ_INSERT_HEAD(&sess->ccb_pool, ccb, chain);
    334 	}
    335 }
    336 
    337 /*
    338  * suspend_ccb:
    339  *    Put CCB on wait queue
    340  */
    341 void
    342 suspend_ccb(ccb_t *ccb, bool yes)
    343 {
    344 	connection_t *conn;
    345 
    346 	conn = ccb->connection;
    347 	if (yes) {
    348 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    349 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    350 		TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain);
    351 		ccb->flags |= CCBF_WAITQUEUE;
    352 	} else if (ccb->flags & CCBF_WAITQUEUE) {
    353 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    354 		TAILQ_REMOVE(&conn->ccbs_waiting, ccb, chain);
    355 		ccb->flags &= ~CCBF_WAITQUEUE;
    356 	}
    357 }
    358 
    359 /*
    360  * throttle_ccb:
    361  *    Put CCB on throttling queue
    362  */
    363 void
    364 throttle_ccb(ccb_t *ccb, bool yes)
    365 {
    366 	session_t *sess;
    367 
    368 	KASSERT(mutex_owned(&sess->lock));
    369 
    370 	sess = ccb->session;
    371 	if (yes) {
    372 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    373 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    374 		TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain);
    375 		ccb->flags |= CCBF_THROTTLING;
    376 	} else if (ccb->flags & CCBF_THROTTLING) {
    377 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    378 		TAILQ_REMOVE(&sess->ccbs_throttled, ccb, chain);
    379 		ccb->flags &= ~CCBF_THROTTLING;
    380 	}
    381 }
    382 
    383 
    384 /*
    385  * wake_ccb:
    386  *    Wake up (or dispose of) a CCB. Depending on the CCB's disposition,
    387  *    either wake up the requesting thread, signal SCSIPI that we're done,
    388  *    or just free the CCB for CCBDISP_FREE.
    389  *
    390  *    Parameter:  The CCB to handle and the new status of the CCB
    391  */
    392 
    393 void
    394 wake_ccb(ccb_t *ccb, uint32_t status)
    395 {
    396 	ccb_disp_t disp;
    397 	connection_t *conn;
    398 
    399 	conn = ccb->connection;
    400 
    401 #ifdef ISCSI_DEBUG
    402 	DEBC(conn, 9, ("CCB done, ccb = %p, disp = %d\n",
    403 		ccb, ccb->disp));
    404 #endif
    405 
    406 	ccb_timeout_stop(ccb);
    407 
    408 	mutex_enter(&conn->lock);
    409 	disp = ccb->disp;
    410 	if (disp <= CCBDISP_NOWAIT ||
    411 		(disp == CCBDISP_DEFER && conn->state <= ST_WINDING_DOWN)) {
    412 		mutex_exit(&conn->lock);
    413 		return;
    414 	}
    415 
    416 	suspend_ccb(ccb, FALSE);
    417 	throttle_ccb(ccb, FALSE);
    418 
    419 	/* change the disposition so nobody tries this again */
    420 	ccb->disp = CCBDISP_BUSY;
    421 	ccb->status = status;
    422 	mutex_exit(&conn->lock);
    423 
    424 	switch (disp) {
    425 	case CCBDISP_FREE:
    426 		free_ccb(ccb);
    427 		break;
    428 
    429 	case CCBDISP_WAIT:
    430 		cv_broadcast(&conn->ccb_cv);
    431 		break;
    432 
    433 	case CCBDISP_SCSIPI:
    434 		iscsi_done(ccb);
    435 		free_ccb(ccb);
    436 		break;
    437 
    438 	case CCBDISP_DEFER:
    439 		break;
    440 
    441 	default:
    442 		DEBC(conn, 1, ("CCB done, ccb = %p, invalid disposition %d", ccb, disp));
    443 		free_ccb(ccb);
    444 		break;
    445 	}
    446 }
    447 
    448 /*****************************************************************************
    449  * PDU management functions
    450  *****************************************************************************/
    451 
    452 /*
    453  * get_pdu:
    454  *    Get a PDU for the SCSI operation.
    455  *
    456  *    Parameter:
    457  *          conn     The connection this PDU should be associated with
    458  *          waitok   OK to wait for PDU if TRUE
    459  *
    460  *    Returns:    The PDU or NULL if none is available and waitok is FALSE.
    461  */
    462 
    463 pdu_t *
    464 get_pdu(connection_t *conn, bool waitok)
    465 {
    466 	pdu_t *pdu;
    467 
    468 	mutex_enter(&conn->lock);
    469 	do {
    470 		pdu = TAILQ_FIRST(&conn->pdu_pool);
    471 		if (pdu != NULL)
    472 			TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
    473 
    474 		DEB(100, ("get_pdu_c: pdu = %p, waitok = %d\n", pdu, waitok));
    475 
    476 		if (pdu == NULL) {
    477 			if (!waitok || conn->terminating) {
    478 				mutex_exit(&conn->lock);
    479 				return NULL;
    480 			}
    481 			cv_wait(&conn->conn_cv, &conn->lock);
    482 		}
    483 	} while (pdu == NULL);
    484 	mutex_exit(&conn->lock);
    485 
    486 	memset(pdu, 0, sizeof(pdu_t));
    487 	pdu->connection = conn;
    488 	pdu->disp = PDUDISP_FREE;
    489 
    490 	return pdu;
    491 }
    492 
    493 /*
    494  * free_pdu:
    495  *    Put a PDU back onto the free list.
    496  *
    497  *    Parameter:  The PDU.
    498  */
    499 
    500 void
    501 free_pdu(pdu_t *pdu)
    502 {
    503 	connection_t *conn = pdu->connection;
    504 	pdu_disp_t pdisp;
    505 
    506 	if (PDUDISP_UNUSED == (pdisp = pdu->disp))
    507 		return;
    508 	pdu->disp = PDUDISP_UNUSED;
    509 
    510 	mutex_enter(&conn->lock);
    511 	if (pdu->flags & PDUF_INQUEUE) {
    512 		TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
    513 		pdu->flags &= ~PDUF_INQUEUE;
    514 	}
    515 	mutex_exit(&conn->lock);
    516 
    517 	/* free temporary data in this PDU */
    518 	if (pdu->temp_data)
    519 		free(pdu->temp_data, M_TEMP);
    520 
    521 	mutex_enter(&conn->lock);
    522 	TAILQ_INSERT_TAIL(&conn->pdu_pool, pdu, chain);
    523 	mutex_exit(&conn->lock);
    524 
    525 	cv_broadcast(&conn->conn_cv);
    526 }
    527 
    528 /*
    529  *    create_pdus
    530  *       "Create" the pool of PDUs. This doesn't actually create the PDUs
    531  *       (they are allocated with the connection structure), but it links them
    532  *       into the free-list.
    533  *
    534  *    Parameter:  The connection owning the PDUs.
    535  */
    536 
    537 void
    538 create_pdus(connection_t *conn)
    539 {
    540 	int i;
    541 	pdu_t *pdu;
    542 
    543 	/* Note: PDUs are initialized to 0 with connection structure */
    544 
    545 	for (i = 0, pdu = conn->pdu; i < PDUS_PER_CONNECTION; i++, pdu++) {
    546 		TAILQ_INSERT_HEAD(&conn->pdu_pool, pdu, chain);
    547 	}
    548 }
    549 
    550 
    551 /*****************************************************************************
    552  * Serial Number management functions
    553  *****************************************************************************/
    554 
    555 /*
    556  * init_sernum:
    557  *    Initialize serial number buffer variables.
    558  *
    559  *    Parameter:
    560  *          buff   The serial number buffer.
    561  */
    562 
    563 void
    564 init_sernum(sernum_buffer_t *buff)
    565 {
    566 
    567 	buff->bottom = 0;
    568 	buff->top = 0;
    569 	buff->next_sn = 0;
    570 	buff->ExpSN = 0;
    571 }
    572 
    573 
    574 /*
    575  * add_sernum:
    576  *    Add a received serial number to the buffer.
    577  *    If the serial number is smaller than the expected one, it is ignored.
    578  *    If it is larger, all missing serial numbers are added as well.
    579  *
    580  *    Parameter:
    581  *          buff   The serial number buffer.
    582  *          num   The received serial number
    583  *
    584  *    Returns:
    585  *          0     if the received block is a duplicate
    586  *          1     if the number is the expected one
    587  *          >1    if the numer is > the expected value, in this case the
    588  *                return value is the number of unacknowledged blocks
    589  *          <0    if the buffer is full (i.e. an excessive number of blocks
    590  *                is unacknowledged)
    591  */
    592 
    593 int
    594 add_sernum(sernum_buffer_t *buff, uint32_t num)
    595 {
    596 	int i, t, b;
    597 	uint32_t n;
    598 	int32_t diff;
    599 
    600 	/*
    601 	 * next_sn is the next expected SN, so normally diff should be 1.
    602 	 */
    603 	n = buff->next_sn;
    604 	diff = (num - n) + 1;
    605 
    606 	if (diff <= 0) {
    607 		return 0;				/* ignore if SN is smaller than expected (dup or retransmit) */
    608 	}
    609 
    610 	buff->next_sn = num + 1;
    611 	t = buff->top;
    612 	b = buff->bottom;
    613 
    614 	for (i = 0; i < diff; i++) {
    615 		buff->sernum[t] = n++;
    616 		buff->ack[t] = false;
    617 		t = (t + 1) % SERNUM_BUFFER_LENGTH;
    618 		if (t == b) {
    619 			DEB(1, ("AddSernum: Buffer Full! num %d, diff %d\n", num, diff));
    620 			return -1;
    621 		}
    622 	}
    623 
    624 	buff->top = t;
    625 	DEB(10, ("AddSernum bottom %d [%d], top %d, num %u, diff %d\n",
    626 			 b, buff->sernum[b], buff->top, num, diff));
    627 
    628 	return diff;
    629 }
    630 
    631 
    632 /*
    633  * ack_sernum:
    634  *    Mark a received serial number as acknowledged. This does not necessarily
    635  *    change the associated ExpSN if there are lower serial numbers in the
    636  *    buffer.
    637  *
    638  *    Parameter:
    639  *          buff   The serial number buffer.
    640  *          num   The serial number to acknowledge.
    641  *
    642  *    Returns:    The value of ExpSN.
    643  */
    644 
    645 uint32_t
    646 ack_sernum(sernum_buffer_t *buff, uint32_t num)
    647 {
    648 	int b = buff->bottom;
    649 	int t = buff->top;
    650 
    651 	/* shortcut for most likely case */
    652 	if (t == (b + 1) && num == buff->sernum[b]) {
    653 		/* buffer is now empty, reset top */
    654 		buff->top = b;
    655 	} else if (b != t) {
    656 		for (; b != t; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    657 			if (!sn_a_lt_b(buff->sernum[b], num))
    658 				break;
    659 		}
    660 		if (num == buff->sernum[b]) {
    661 			if (b == buff->bottom)
    662 				buff->bottom = (b + 1) % SERNUM_BUFFER_LENGTH;
    663 			else
    664 				buff->ack[b] = true;
    665 		}
    666 
    667 		for (b = buff->bottom, num = buff->sernum[b] - 1;
    668 			 b != t && buff->ack[b]; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    669 			num = buff->sernum[b];
    670 		}
    671 	}
    672 
    673 	if (!sn_a_lt_b(num, buff->ExpSN))
    674 		buff->ExpSN = num + 1;
    675 
    676 	DEB(10, ("AckSernum bottom %d, top %d, num %d ExpSN %d\n",
    677 			 buff->bottom, buff->top, num, buff->ExpSN));
    678 
    679 	return buff->ExpSN;
    680 }
    681 
    682 /*
    683  * next_sernum:
    684  *   Return the current command serial number of the session
    685  *   and optionally increment it for the next query
    686  */
    687 uint32_t
    688 get_sernum(session_t *sess, bool bump)
    689 {
    690 	uint32_t sn;
    691 
    692 	KASSERT(mutex_owned(&sess->lock));
    693 
    694 	sn = sess->CmdSN;
    695 	if (bump)
    696 		atomic_inc_32(&sess->CmdSN);
    697 	return sn;
    698 }
    699 
    700 /*
    701  * sernum_in_window:
    702  *   Check wether serial number is in send window
    703  *
    704  */
    705 int
    706 sernum_in_window(session_t *sess)
    707 {
    708 
    709 	KASSERT(mutex_owned(&sess->lock));
    710 	return sn_a_le_b(sess->CmdSN, sess->MaxCmdSN);
    711 }
    712 
    713