Home | History | Annotate | Line # | Download | only in iscsi
iscsi_utils.c revision 1.18
      1 /*	$NetBSD: iscsi_utils.c,v 1.18 2016/06/05 09:21:14 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 	sess = ccb->session;
    371 
    372 	KASSERT(mutex_owned(&sess->lock));
    373 
    374 	if (yes) {
    375 		KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
    376 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    377 		TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain);
    378 		ccb->flags |= CCBF_THROTTLING;
    379 	} else if (ccb->flags & CCBF_THROTTLING) {
    380 		KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
    381 		TAILQ_REMOVE(&sess->ccbs_throttled, ccb, chain);
    382 		ccb->flags &= ~CCBF_THROTTLING;
    383 	}
    384 }
    385 
    386 
    387 /*
    388  * wake_ccb:
    389  *    Wake up (or dispose of) a CCB. Depending on the CCB's disposition,
    390  *    either wake up the requesting thread, signal SCSIPI that we're done,
    391  *    or just free the CCB for CCBDISP_FREE.
    392  *
    393  *    Parameter:  The CCB to handle and the new status of the CCB
    394  */
    395 
    396 void
    397 wake_ccb(ccb_t *ccb, uint32_t status)
    398 {
    399 	ccb_disp_t disp;
    400 	connection_t *conn;
    401 	session_t *sess;
    402 
    403 	conn = ccb->connection;
    404 	sess = ccb->session;
    405 
    406 #ifdef ISCSI_DEBUG
    407 	DEBC(conn, 9, ("CCB done, ccb = %p, disp = %d\n",
    408 		ccb, ccb->disp));
    409 #endif
    410 
    411 	ccb_timeout_stop(ccb);
    412 
    413 	mutex_enter(&conn->lock);
    414 	disp = ccb->disp;
    415 	if (disp <= CCBDISP_NOWAIT ||
    416 		(disp == CCBDISP_DEFER && conn->state <= ST_WINDING_DOWN)) {
    417 		mutex_exit(&conn->lock);
    418 		return;
    419 	}
    420 
    421 	suspend_ccb(ccb, FALSE);
    422 
    423 	/* change the disposition so nobody tries this again */
    424 	ccb->disp = CCBDISP_BUSY;
    425 	ccb->status = status;
    426 	mutex_exit(&conn->lock);
    427 
    428 	mutex_enter(&sess->lock);
    429 	throttle_ccb(ccb, FALSE);
    430 	mutex_exit(&sess->lock);
    431 
    432 	switch (disp) {
    433 	case CCBDISP_FREE:
    434 		free_ccb(ccb);
    435 		break;
    436 
    437 	case CCBDISP_WAIT:
    438 		cv_broadcast(&conn->ccb_cv);
    439 		break;
    440 
    441 	case CCBDISP_SCSIPI:
    442 		iscsi_done(ccb);
    443 		free_ccb(ccb);
    444 		break;
    445 
    446 	case CCBDISP_DEFER:
    447 		break;
    448 
    449 	default:
    450 		DEBC(conn, 1, ("CCB done, ccb = %p, invalid disposition %d", ccb, disp));
    451 		free_ccb(ccb);
    452 		break;
    453 	}
    454 }
    455 
    456 /*****************************************************************************
    457  * PDU management functions
    458  *****************************************************************************/
    459 
    460 /*
    461  * get_pdu:
    462  *    Get a PDU for the SCSI operation.
    463  *
    464  *    Parameter:
    465  *          conn     The connection this PDU should be associated with
    466  *          waitok   OK to wait for PDU if TRUE
    467  *
    468  *    Returns:    The PDU or NULL if none is available and waitok is FALSE.
    469  */
    470 
    471 pdu_t *
    472 get_pdu(connection_t *conn, bool waitok)
    473 {
    474 	pdu_t *pdu;
    475 
    476 	mutex_enter(&conn->lock);
    477 	do {
    478 		pdu = TAILQ_FIRST(&conn->pdu_pool);
    479 		if (pdu != NULL)
    480 			TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
    481 
    482 		DEB(100, ("get_pdu_c: pdu = %p, waitok = %d\n", pdu, waitok));
    483 
    484 		if (pdu == NULL) {
    485 			if (!waitok || conn->terminating) {
    486 				mutex_exit(&conn->lock);
    487 				return NULL;
    488 			}
    489 			cv_wait(&conn->conn_cv, &conn->lock);
    490 		}
    491 	} while (pdu == NULL);
    492 	mutex_exit(&conn->lock);
    493 
    494 	memset(pdu, 0, sizeof(pdu_t));
    495 	pdu->connection = conn;
    496 	pdu->disp = PDUDISP_FREE;
    497 
    498 	return pdu;
    499 }
    500 
    501 /*
    502  * free_pdu:
    503  *    Put a PDU back onto the free list.
    504  *
    505  *    Parameter:  The PDU.
    506  */
    507 
    508 void
    509 free_pdu(pdu_t *pdu)
    510 {
    511 	connection_t *conn = pdu->connection;
    512 	pdu_disp_t pdisp;
    513 
    514 	KASSERT((pdu->flags & PDUF_INQUEUE) == 0);
    515 
    516 	if (PDUDISP_UNUSED == (pdisp = pdu->disp))
    517 		return;
    518 	pdu->disp = PDUDISP_UNUSED;
    519 
    520 	/* free temporary data in this PDU */
    521 	if (pdu->temp_data)
    522 		free(pdu->temp_data, M_TEMP);
    523 
    524 	mutex_enter(&conn->lock);
    525 	TAILQ_INSERT_TAIL(&conn->pdu_pool, pdu, chain);
    526 	mutex_exit(&conn->lock);
    527 
    528 	cv_broadcast(&conn->conn_cv);
    529 }
    530 
    531 /*
    532  *    create_pdus
    533  *       "Create" the pool of PDUs. This doesn't actually create the PDUs
    534  *       (they are allocated with the connection structure), but it links them
    535  *       into the free-list.
    536  *
    537  *    Parameter:  The connection owning the PDUs.
    538  */
    539 
    540 void
    541 create_pdus(connection_t *conn)
    542 {
    543 	int i;
    544 	pdu_t *pdu;
    545 
    546 	/* Note: PDUs are initialized to 0 with connection structure */
    547 
    548 	for (i = 0, pdu = conn->pdu; i < PDUS_PER_CONNECTION; i++, pdu++) {
    549 		TAILQ_INSERT_HEAD(&conn->pdu_pool, pdu, chain);
    550 	}
    551 }
    552 
    553 
    554 /*****************************************************************************
    555  * Serial Number management functions
    556  *****************************************************************************/
    557 
    558 /*
    559  * init_sernum:
    560  *    Initialize serial number buffer variables.
    561  *
    562  *    Parameter:
    563  *          buff   The serial number buffer.
    564  */
    565 
    566 void
    567 init_sernum(sernum_buffer_t *buff)
    568 {
    569 
    570 	buff->bottom = 0;
    571 	buff->top = 0;
    572 	buff->next_sn = 0;
    573 	buff->ExpSN = 0;
    574 }
    575 
    576 
    577 /*
    578  * add_sernum:
    579  *    Add a received serial number to the buffer.
    580  *    If the serial number is smaller than the expected one, it is ignored.
    581  *    If it is larger, all missing serial numbers are added as well.
    582  *
    583  *    Parameter:
    584  *          buff   The serial number buffer.
    585  *          num   The received serial number
    586  *
    587  *    Returns:
    588  *          0     if the received block is a duplicate
    589  *          1     if the number is the expected one
    590  *          >1    if the numer is > the expected value, in this case the
    591  *                return value is the number of unacknowledged blocks
    592  *          <0    if the buffer is full (i.e. an excessive number of blocks
    593  *                is unacknowledged)
    594  */
    595 
    596 int
    597 add_sernum(sernum_buffer_t *buff, uint32_t num)
    598 {
    599 	int i, t, b;
    600 	uint32_t n;
    601 	int32_t diff;
    602 
    603 	/*
    604 	 * next_sn is the next expected SN, so normally diff should be 1.
    605 	 */
    606 	n = buff->next_sn;
    607 	diff = (num - n) + 1;
    608 
    609 	if (diff <= 0) {
    610 		return 0;				/* ignore if SN is smaller than expected (dup or retransmit) */
    611 	}
    612 
    613 	buff->next_sn = num + 1;
    614 	t = buff->top;
    615 	b = buff->bottom;
    616 
    617 	for (i = 0; i < diff; i++) {
    618 		buff->sernum[t] = n++;
    619 		buff->ack[t] = false;
    620 		t = (t + 1) % SERNUM_BUFFER_LENGTH;
    621 		if (t == b) {
    622 			DEB(1, ("AddSernum: Buffer Full! num %d, diff %d\n", num, diff));
    623 			return -1;
    624 		}
    625 	}
    626 
    627 	buff->top = t;
    628 	DEB(11, ("AddSernum bottom %d [%d], top %d, num %u, diff %d\n",
    629 			 b, buff->sernum[b], buff->top, num, diff));
    630 
    631 	return diff;
    632 }
    633 
    634 
    635 /*
    636  * ack_sernum:
    637  *    Mark a received serial number as acknowledged. This does not necessarily
    638  *    change the associated ExpSN if there are lower serial numbers in the
    639  *    buffer.
    640  *
    641  *    Parameter:
    642  *          buff   The serial number buffer.
    643  *          num   The serial number to acknowledge.
    644  *
    645  *    Returns:    The value of ExpSN.
    646  */
    647 
    648 uint32_t
    649 ack_sernum(sernum_buffer_t *buff, uint32_t num)
    650 {
    651 	int b = buff->bottom;
    652 	int t = buff->top;
    653 
    654 	/* shortcut for most likely case */
    655 	if (t == (b + 1) && num == buff->sernum[b]) {
    656 		/* buffer is now empty, reset top */
    657 		buff->top = b;
    658 	} else if (b != t) {
    659 		for (; b != t; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    660 			if (!sn_a_lt_b(buff->sernum[b], num))
    661 				break;
    662 		}
    663 		if (num == buff->sernum[b]) {
    664 			if (b == buff->bottom)
    665 				buff->bottom = (b + 1) % SERNUM_BUFFER_LENGTH;
    666 			else
    667 				buff->ack[b] = true;
    668 		}
    669 
    670 		for (b = buff->bottom, num = buff->sernum[b] - 1;
    671 			 b != t && buff->ack[b]; b = (b + 1) % SERNUM_BUFFER_LENGTH) {
    672 			num = buff->sernum[b];
    673 		}
    674 	}
    675 
    676 	if (!sn_a_lt_b(num, buff->ExpSN))
    677 		buff->ExpSN = num + 1;
    678 
    679 	DEB(11, ("AckSernum bottom %d, top %d, num %d ExpSN %d\n",
    680 			 buff->bottom, buff->top, num, buff->ExpSN));
    681 
    682 	return buff->ExpSN;
    683 }
    684 
    685 /*
    686  * next_sernum:
    687  *   Return the current command serial number of the session
    688  *   and optionally increment it for the next query
    689  */
    690 uint32_t
    691 get_sernum(session_t *sess, bool bump)
    692 {
    693 	uint32_t sn;
    694 
    695 	KASSERT(mutex_owned(&sess->lock));
    696 
    697 	sn = sess->CmdSN;
    698 	if (bump)
    699 		atomic_inc_32(&sess->CmdSN);
    700 	return sn;
    701 }
    702 
    703 /*
    704  * sernum_in_window:
    705  *   Check wether serial number is in send window
    706  *
    707  */
    708 int
    709 sernum_in_window(session_t *sess)
    710 {
    711 
    712 	KASSERT(mutex_owned(&sess->lock));
    713 	return sn_a_le_b(sess->CmdSN, sess->MaxCmdSN);
    714 }
    715 
    716