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