1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Modified to be used by inetboot. */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <socket_impl.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 34*7c478bd9Sstevel@tonic-gate #include <netinet/tcp.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 37*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 38*7c478bd9Sstevel@tonic-gate #include <netinet/ip6.h> 39*7c478bd9Sstevel@tonic-gate #include <inet/common.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/salib.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include "tcp_inet.h" 44*7c478bd9Sstevel@tonic-gate #include "tcp_sack.h" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* 47*7c478bd9Sstevel@tonic-gate * To insert a new blk to the array of SACK blk in receiver. 48*7c478bd9Sstevel@tonic-gate * 49*7c478bd9Sstevel@tonic-gate * Parameters: 50*7c478bd9Sstevel@tonic-gate * sack_blk_t *head: pointer to the array of SACK blks. 51*7c478bd9Sstevel@tonic-gate * tcp_seq begin: starting seq num of the new blk. 52*7c478bd9Sstevel@tonic-gate * tcp_seq end: ending seq num of the new blk. 53*7c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of SACK blks on the list. 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate void 56*7c478bd9Sstevel@tonic-gate tcp_sack_insert(sack_blk_t *head, tcp_seq begin, tcp_seq end, int32_t *num) 57*7c478bd9Sstevel@tonic-gate { 58*7c478bd9Sstevel@tonic-gate int32_t i, j, old_num, new_num; 59*7c478bd9Sstevel@tonic-gate sack_blk_t tmp[MAX_SACK_BLK - 1]; 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* The array is empty, just add the new one. */ 62*7c478bd9Sstevel@tonic-gate if (*num == 0) { 63*7c478bd9Sstevel@tonic-gate head[0].begin = begin; 64*7c478bd9Sstevel@tonic-gate head[0].end = end; 65*7c478bd9Sstevel@tonic-gate *num = 1; 66*7c478bd9Sstevel@tonic-gate return; 67*7c478bd9Sstevel@tonic-gate } 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * Check for overlap. There are five cases. 71*7c478bd9Sstevel@tonic-gate * 72*7c478bd9Sstevel@tonic-gate * 1. there is no overlap with any other SACK blks. 73*7c478bd9Sstevel@tonic-gate * 2. new SACK blk is completely contained in another blk. 74*7c478bd9Sstevel@tonic-gate * 3. tail part of new SACK blk overlaps with another blk. 75*7c478bd9Sstevel@tonic-gate * 4. head part of new SACK blk overlaps with another blk. 76*7c478bd9Sstevel@tonic-gate * 5. new SACK blk completely contains another blk. 77*7c478bd9Sstevel@tonic-gate * 78*7c478bd9Sstevel@tonic-gate * Use tmp to hold old SACK blks. After the loop, copy them back 79*7c478bd9Sstevel@tonic-gate * to head. 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate old_num = *num; 82*7c478bd9Sstevel@tonic-gate if (old_num > MAX_SACK_BLK - 1) { 83*7c478bd9Sstevel@tonic-gate old_num = MAX_SACK_BLK - 1; 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate new_num = old_num; 86*7c478bd9Sstevel@tonic-gate j = 0; 87*7c478bd9Sstevel@tonic-gate for (i = 0; i < old_num; i++) { 88*7c478bd9Sstevel@tonic-gate if (SEQ_LT(end, head[i].begin) || SEQ_GT(begin, head[i].end)) { 89*7c478bd9Sstevel@tonic-gate /* Case 1: continue to check. */ 90*7c478bd9Sstevel@tonic-gate tmp[j].begin = head[i].begin; 91*7c478bd9Sstevel@tonic-gate tmp[j].end = head[i].end; 92*7c478bd9Sstevel@tonic-gate j++; 93*7c478bd9Sstevel@tonic-gate continue; 94*7c478bd9Sstevel@tonic-gate } else if (SEQ_GEQ(begin, head[i].begin) && 95*7c478bd9Sstevel@tonic-gate SEQ_LEQ(end, head[i].end)) { 96*7c478bd9Sstevel@tonic-gate /* Case 2: re-insert the old blk to the head. */ 97*7c478bd9Sstevel@tonic-gate begin = head[i].begin; 98*7c478bd9Sstevel@tonic-gate end = head[i].end; 99*7c478bd9Sstevel@tonic-gate } else if (SEQ_LEQ(end, head[i].end) && 100*7c478bd9Sstevel@tonic-gate SEQ_GEQ(end, head[i].begin)) { 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * Case 3: Extend the new blk, remove the old one 103*7c478bd9Sstevel@tonic-gate * and continue to check. 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate end = head[i].end; 106*7c478bd9Sstevel@tonic-gate } else if (SEQ_GEQ(begin, head[i].begin) && 107*7c478bd9Sstevel@tonic-gate SEQ_LEQ(begin, head[i].end)) { 108*7c478bd9Sstevel@tonic-gate /* Case 4 */ 109*7c478bd9Sstevel@tonic-gate begin = head[i].begin; 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * Common code for all cases except the first one, which 113*7c478bd9Sstevel@tonic-gate * copies the original SACK blk into the tmp storage. Other 114*7c478bd9Sstevel@tonic-gate * cases remove the original SACK blk by not copying into 115*7c478bd9Sstevel@tonic-gate * tmp storage. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate new_num--; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate head[0].begin = begin; 121*7c478bd9Sstevel@tonic-gate head[0].end = end; 122*7c478bd9Sstevel@tonic-gate for (i = 0; i < new_num; i++) { 123*7c478bd9Sstevel@tonic-gate head[i+1].begin = tmp[i].begin; 124*7c478bd9Sstevel@tonic-gate head[i+1].end = tmp[i].end; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate *num = new_num + 1; 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * To remove a SACK block. 132*7c478bd9Sstevel@tonic-gate * 133*7c478bd9Sstevel@tonic-gate * Parameters: 134*7c478bd9Sstevel@tonic-gate * sack_blk_t *head: pointer to the array of SACK blks. 135*7c478bd9Sstevel@tonic-gate * tcp_seq end: to remove all sack blk with seq num less than end. 136*7c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of SACK blks in the array. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate void 139*7c478bd9Sstevel@tonic-gate tcp_sack_remove(sack_blk_t *head, tcp_seq end, int32_t *num) 140*7c478bd9Sstevel@tonic-gate { 141*7c478bd9Sstevel@tonic-gate sack_blk_t tmp[MAX_SACK_BLK]; 142*7c478bd9Sstevel@tonic-gate int32_t i, j, old_num, new_num; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate if (*num == 0) 145*7c478bd9Sstevel@tonic-gate return; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate old_num = *num; 148*7c478bd9Sstevel@tonic-gate new_num = old_num; 149*7c478bd9Sstevel@tonic-gate j = 0; 150*7c478bd9Sstevel@tonic-gate /* Walk thru the whole list and copy the new list to tmp[]. */ 151*7c478bd9Sstevel@tonic-gate for (i = 0; i < old_num; i++) { 152*7c478bd9Sstevel@tonic-gate if (SEQ_GT(end, head[i].begin)) { 153*7c478bd9Sstevel@tonic-gate /* 154*7c478bd9Sstevel@tonic-gate * Check to see if the old SACK blk needs to be 155*7c478bd9Sstevel@tonic-gate * removed or updated. If the old blk is just 156*7c478bd9Sstevel@tonic-gate * partially covered, update begin and continue. 157*7c478bd9Sstevel@tonic-gate * If the old blk is completely covered, remove it 158*7c478bd9Sstevel@tonic-gate * and continue to check. 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate if (SEQ_GEQ(end, head[i].end)) { 161*7c478bd9Sstevel@tonic-gate new_num--; 162*7c478bd9Sstevel@tonic-gate continue; 163*7c478bd9Sstevel@tonic-gate } else { 164*7c478bd9Sstevel@tonic-gate tmp[j].begin = end; 165*7c478bd9Sstevel@tonic-gate tmp[j].end = head[i].end; 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate } else { 168*7c478bd9Sstevel@tonic-gate tmp[j].begin = head[i].begin; 169*7c478bd9Sstevel@tonic-gate tmp[j].end = head[i].end; 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate j++; 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate /* Copy tmp[] back to the original list. */ 174*7c478bd9Sstevel@tonic-gate for (i = 0; i < new_num; i++) { 175*7c478bd9Sstevel@tonic-gate head[i].begin = tmp[i].begin; 176*7c478bd9Sstevel@tonic-gate head[i].end = tmp[i].end; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate *num = new_num; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* 183*7c478bd9Sstevel@tonic-gate * Use the SACK info to insert a "notsack'ed" blk. The notsack'ed blk list 184*7c478bd9Sstevel@tonic-gate * contains the list of blks which have not been selectively acknowledged 185*7c478bd9Sstevel@tonic-gate * by the receiver. The SACK info is a blk which is being selectively 186*7c478bd9Sstevel@tonic-gate * acknowledged by the receiver. 187*7c478bd9Sstevel@tonic-gate * 188*7c478bd9Sstevel@tonic-gate * Parameters: 189*7c478bd9Sstevel@tonic-gate * notsack_blk_t **head: address of the pointer to the list of notsack'ed 190*7c478bd9Sstevel@tonic-gate * blks. 191*7c478bd9Sstevel@tonic-gate * tcp_seq begin: starting seq num of the SACK info. 192*7c478bd9Sstevel@tonic-gate * tcp_seq end: ending seq num of the SACK info. 193*7c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of notsack'ed blk on the list. 194*7c478bd9Sstevel@tonic-gate * uint32_t *sum: (referenced) total num of bytes of all the notsack'ed 195*7c478bd9Sstevel@tonic-gate * blks. 196*7c478bd9Sstevel@tonic-gate */ 197*7c478bd9Sstevel@tonic-gate void 198*7c478bd9Sstevel@tonic-gate tcp_notsack_insert(notsack_blk_t **head, tcp_seq begin, tcp_seq end, 199*7c478bd9Sstevel@tonic-gate int32_t *num, uint32_t *sum) 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate notsack_blk_t *prev, *tmp, *new; 202*7c478bd9Sstevel@tonic-gate uint32_t tmp_sum, tmp_num; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (*head == NULL) { 205*7c478bd9Sstevel@tonic-gate return; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate tmp = *head; 209*7c478bd9Sstevel@tonic-gate prev = NULL; 210*7c478bd9Sstevel@tonic-gate /* Find the right place of updating the list. */ 211*7c478bd9Sstevel@tonic-gate while ((tmp != NULL) && SEQ_LEQ(tmp->end, begin)) { 212*7c478bd9Sstevel@tonic-gate prev = tmp; 213*7c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++; 214*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * This can happen only when TCP sends new data but the notsack list 219*7c478bd9Sstevel@tonic-gate * is not updated. 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 222*7c478bd9Sstevel@tonic-gate return; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * This means the new SACK info covers something that is not on 227*7c478bd9Sstevel@tonic-gate * the list anymore. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate if (SEQ_LEQ(end, tmp->begin)) { 230*7c478bd9Sstevel@tonic-gate return; 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /* The SACK info covers up to this blk. So just check for this blk. */ 234*7c478bd9Sstevel@tonic-gate if (SEQ_LEQ(end, tmp->end)) { 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * Only this notsack'ed blk is completely covered. Delete 237*7c478bd9Sstevel@tonic-gate * it and return. 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate if (end == tmp->end && SEQ_LEQ(begin, tmp->begin)) { 240*7c478bd9Sstevel@tonic-gate if (prev != NULL) { 241*7c478bd9Sstevel@tonic-gate prev->next = tmp->next; 242*7c478bd9Sstevel@tonic-gate } else { 243*7c478bd9Sstevel@tonic-gate *head = tmp->next; 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate (*num)--; 246*7c478bd9Sstevel@tonic-gate *sum -= tmp->end - tmp->begin; 247*7c478bd9Sstevel@tonic-gate bkmem_free(tmp, sizeof (notsack_blk_t)); 248*7c478bd9Sstevel@tonic-gate return; 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate /* This blk is partially covered. */ 251*7c478bd9Sstevel@tonic-gate if (SEQ_GEQ(begin, tmp->begin)) { 252*7c478bd9Sstevel@tonic-gate /* Check what needs to be updated. */ 253*7c478bd9Sstevel@tonic-gate if (begin == tmp->begin) { 254*7c478bd9Sstevel@tonic-gate *sum -= end - tmp->begin; 255*7c478bd9Sstevel@tonic-gate tmp->begin = end; 256*7c478bd9Sstevel@tonic-gate } else if (end == tmp->end) { 257*7c478bd9Sstevel@tonic-gate *sum -= tmp->end - begin; 258*7c478bd9Sstevel@tonic-gate tmp->end = begin; 259*7c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++; 260*7c478bd9Sstevel@tonic-gate } else { 261*7c478bd9Sstevel@tonic-gate /* Split the notsack blk. */ 262*7c478bd9Sstevel@tonic-gate if ((new = (notsack_blk_t *)bkmem_alloc( 263*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t))) == NULL) { 264*7c478bd9Sstevel@tonic-gate return; 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate new->end = tmp->end; 267*7c478bd9Sstevel@tonic-gate new->begin = end; 268*7c478bd9Sstevel@tonic-gate new->next = tmp->next; 269*7c478bd9Sstevel@tonic-gate new->sack_cnt = 0; 270*7c478bd9Sstevel@tonic-gate tmp->end = begin; 271*7c478bd9Sstevel@tonic-gate tmp->next = new; 272*7c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++; 273*7c478bd9Sstevel@tonic-gate (*num)++; 274*7c478bd9Sstevel@tonic-gate *sum -= end - begin; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate } else { 277*7c478bd9Sstevel@tonic-gate *sum -= end - tmp->begin; 278*7c478bd9Sstevel@tonic-gate tmp->begin = end; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate return; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* Need to check for coverage of this blk and later blks. */ 284*7c478bd9Sstevel@tonic-gate tmp_sum = *sum; 285*7c478bd9Sstevel@tonic-gate tmp_num = *num; 286*7c478bd9Sstevel@tonic-gate if (SEQ_LT(tmp->begin, begin)) { 287*7c478bd9Sstevel@tonic-gate tmp_sum -= tmp->end - begin; 288*7c478bd9Sstevel@tonic-gate tmp->end = begin; 289*7c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++; 290*7c478bd9Sstevel@tonic-gate prev = tmp; 291*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate while (tmp != NULL) { 295*7c478bd9Sstevel@tonic-gate /* The coverage stops here. */ 296*7c478bd9Sstevel@tonic-gate if (SEQ_GT(tmp->begin, end)) { 297*7c478bd9Sstevel@tonic-gate break; 298*7c478bd9Sstevel@tonic-gate } else { 299*7c478bd9Sstevel@tonic-gate /* Is the blk completely or partially covered? */ 300*7c478bd9Sstevel@tonic-gate if (SEQ_LEQ(tmp->end, end)) { 301*7c478bd9Sstevel@tonic-gate tmp_num--; 302*7c478bd9Sstevel@tonic-gate tmp_sum -= tmp->end - tmp->begin; 303*7c478bd9Sstevel@tonic-gate if (prev != NULL) { 304*7c478bd9Sstevel@tonic-gate prev->next = tmp->next; 305*7c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)tmp, 306*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t)); 307*7c478bd9Sstevel@tonic-gate tmp = prev->next; 308*7c478bd9Sstevel@tonic-gate } else { 309*7c478bd9Sstevel@tonic-gate *head = tmp->next; 310*7c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)tmp, 311*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t)); 312*7c478bd9Sstevel@tonic-gate tmp = *head; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate } else { 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * This blk is partially covered. It also 317*7c478bd9Sstevel@tonic-gate * means it should be the end of coverage. 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate tmp_sum -= end - tmp->begin; 320*7c478bd9Sstevel@tonic-gate tmp->begin = end; 321*7c478bd9Sstevel@tonic-gate break; 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate *num = tmp_num; 326*7c478bd9Sstevel@tonic-gate *sum = tmp_sum; 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate /* 331*7c478bd9Sstevel@tonic-gate * To remove notsack'ed blks. 332*7c478bd9Sstevel@tonic-gate * 333*7c478bd9Sstevel@tonic-gate * Parameters: 334*7c478bd9Sstevel@tonic-gate * notsack_blk_t **head: address of the pointer to the list of notsack'ed 335*7c478bd9Sstevel@tonic-gate * blks. 336*7c478bd9Sstevel@tonic-gate * tcp_seq end: to remove all notsack'ed blk with seq num less than end. 337*7c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of notsack'ed blks. 338*7c478bd9Sstevel@tonic-gate * uint32_t *sum: (referenced) total num of bytes of all the notsack'ed 339*7c478bd9Sstevel@tonic-gate * blks. 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate void 342*7c478bd9Sstevel@tonic-gate tcp_notsack_remove(notsack_blk_t **head, tcp_seq end, int32_t *num, 343*7c478bd9Sstevel@tonic-gate uint32_t *sum) 344*7c478bd9Sstevel@tonic-gate { 345*7c478bd9Sstevel@tonic-gate notsack_blk_t *prev, *tmp; 346*7c478bd9Sstevel@tonic-gate uint32_t tmp_sum = *sum; 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate if (*head == NULL) 349*7c478bd9Sstevel@tonic-gate return; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate prev = NULL; 352*7c478bd9Sstevel@tonic-gate tmp = *head; 353*7c478bd9Sstevel@tonic-gate while (tmp != NULL) { 354*7c478bd9Sstevel@tonic-gate /* There is nothing to discard. */ 355*7c478bd9Sstevel@tonic-gate if (SEQ_GT(tmp->begin, end)) { 356*7c478bd9Sstevel@tonic-gate break; 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* Is the blk completely or partially covered? */ 360*7c478bd9Sstevel@tonic-gate if (SEQ_GEQ(end, tmp->end)) { 361*7c478bd9Sstevel@tonic-gate (*num)--; 362*7c478bd9Sstevel@tonic-gate tmp_sum -= tmp->end - tmp->begin; 363*7c478bd9Sstevel@tonic-gate if (prev == NULL) { 364*7c478bd9Sstevel@tonic-gate *head = tmp->next; 365*7c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)tmp, 366*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t)); 367*7c478bd9Sstevel@tonic-gate tmp = *head; 368*7c478bd9Sstevel@tonic-gate } else { 369*7c478bd9Sstevel@tonic-gate prev->next = tmp->next; 370*7c478bd9Sstevel@tonic-gate bkmem_free((caddr_t)tmp, 371*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t)); 372*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate } else { 375*7c478bd9Sstevel@tonic-gate tmp_sum -= end - tmp->begin; 376*7c478bd9Sstevel@tonic-gate tmp->begin = end; 377*7c478bd9Sstevel@tonic-gate break; 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate *sum = tmp_sum; 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate /* 385*7c478bd9Sstevel@tonic-gate * To update the notsack'ed list when new data is sent. 386*7c478bd9Sstevel@tonic-gate * 387*7c478bd9Sstevel@tonic-gate * Assumption: this should only be called when new notsack blk is to be added. 388*7c478bd9Sstevel@tonic-gate * 389*7c478bd9Sstevel@tonic-gate * Parameters: 390*7c478bd9Sstevel@tonic-gate * notsack_blk_t **head: address of the pointer to the list of notsack'ed 391*7c478bd9Sstevel@tonic-gate * blks. 392*7c478bd9Sstevel@tonic-gate * tcp_seq begin: beginning seq num of new data. 393*7c478bd9Sstevel@tonic-gate * tcp_seq end: ending seq num of new data. 394*7c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of notsack'ed blks. 395*7c478bd9Sstevel@tonic-gate * uint32_t *sum: (referenced) total num of bytes of all the notsack'ed 396*7c478bd9Sstevel@tonic-gate * blks. 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate void tcp_notsack_update(notsack_blk_t **head, tcp_seq begin, tcp_seq end, 399*7c478bd9Sstevel@tonic-gate int32_t *num, uint32_t *sum) 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate notsack_blk_t *tmp; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate tmp = *head; 404*7c478bd9Sstevel@tonic-gate /* If the list is empty, create a new one. */ 405*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 406*7c478bd9Sstevel@tonic-gate if ((tmp = (notsack_blk_t *)bkmem_alloc( 407*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t))) == NULL) { 408*7c478bd9Sstevel@tonic-gate return; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate tmp->begin = begin; 411*7c478bd9Sstevel@tonic-gate tmp->end = end; 412*7c478bd9Sstevel@tonic-gate tmp->next = NULL; 413*7c478bd9Sstevel@tonic-gate tmp->sack_cnt = 0; 414*7c478bd9Sstevel@tonic-gate *head = tmp; 415*7c478bd9Sstevel@tonic-gate *num = 1; 416*7c478bd9Sstevel@tonic-gate *sum = end - begin; 417*7c478bd9Sstevel@tonic-gate return; 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * Find the place to add the new blk. This assumes that new data 422*7c478bd9Sstevel@tonic-gate * is being sent, so the place to insert the new notsack blk is at 423*7c478bd9Sstevel@tonic-gate * the end of the list. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate while (tmp->next != NULL) { 426*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* Does the new blk overlap with old one? */ 430*7c478bd9Sstevel@tonic-gate if (SEQ_GEQ(tmp->end, begin)) { 431*7c478bd9Sstevel@tonic-gate *sum += end - tmp->end; 432*7c478bd9Sstevel@tonic-gate tmp->end = end; 433*7c478bd9Sstevel@tonic-gate } else { 434*7c478bd9Sstevel@tonic-gate /* No. Need to create a new notsack blk. */ 435*7c478bd9Sstevel@tonic-gate tmp->next = (notsack_blk_t *)bkmem_alloc( 436*7c478bd9Sstevel@tonic-gate sizeof (notsack_blk_t)); 437*7c478bd9Sstevel@tonic-gate if (tmp->next != NULL) { 438*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 439*7c478bd9Sstevel@tonic-gate tmp->begin = begin; 440*7c478bd9Sstevel@tonic-gate tmp->end = end; 441*7c478bd9Sstevel@tonic-gate tmp->next = NULL; 442*7c478bd9Sstevel@tonic-gate tmp->sack_cnt = 0; 443*7c478bd9Sstevel@tonic-gate (*num)++; 444*7c478bd9Sstevel@tonic-gate *sum += end - begin; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate } 448