17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*66cd0f60SKacheong Poon * Common Development and Distribution License (the "License").
6*66cd0f60SKacheong Poon * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*66cd0f60SKacheong Poon * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/types.h>
267c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
277c478bd9Sstevel@tonic-gate #include <sys/debug.h>
287c478bd9Sstevel@tonic-gate #include <netinet/tcp.h>
297c478bd9Sstevel@tonic-gate #include <sys/systm.h>
307c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
317c478bd9Sstevel@tonic-gate #include <netinet/in.h>
327c478bd9Sstevel@tonic-gate #include <netinet/ip6.h>
337c478bd9Sstevel@tonic-gate #include <inet/common.h>
347c478bd9Sstevel@tonic-gate #include <inet/ip.h>
357c478bd9Sstevel@tonic-gate #include <inet/tcp.h>
367c478bd9Sstevel@tonic-gate
37*66cd0f60SKacheong Poon /* kmem cache for notsack_blk_t */
38*66cd0f60SKacheong Poon kmem_cache_t *tcp_notsack_blk_cache;
39*66cd0f60SKacheong Poon
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate * To insert a new blk to the array of SACK blk in receiver.
427c478bd9Sstevel@tonic-gate *
437c478bd9Sstevel@tonic-gate * Parameters:
447c478bd9Sstevel@tonic-gate * sack_blk_t *head: pointer to the array of SACK blks.
457c478bd9Sstevel@tonic-gate * tcp_seq begin: starting seq num of the new blk.
467c478bd9Sstevel@tonic-gate * tcp_seq end: ending seq num of the new blk.
477c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of SACK blks on the list.
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate void
tcp_sack_insert(sack_blk_t * head,tcp_seq begin,tcp_seq end,int32_t * num)507c478bd9Sstevel@tonic-gate tcp_sack_insert(sack_blk_t *head, tcp_seq begin, tcp_seq end, int32_t *num)
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate int32_t i, j, old_num, new_num;
537c478bd9Sstevel@tonic-gate sack_blk_t tmp[MAX_SACK_BLK - 1];
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate /* The array is empty, just add the new one. */
567c478bd9Sstevel@tonic-gate if (*num == 0) {
577c478bd9Sstevel@tonic-gate head[0].begin = begin;
587c478bd9Sstevel@tonic-gate head[0].end = end;
597c478bd9Sstevel@tonic-gate *num = 1;
607c478bd9Sstevel@tonic-gate return;
617c478bd9Sstevel@tonic-gate }
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * Check for overlap. There are five cases.
657c478bd9Sstevel@tonic-gate *
667c478bd9Sstevel@tonic-gate * 1. there is no overlap with any other SACK blks.
677c478bd9Sstevel@tonic-gate * 2. new SACK blk is completely contained in another blk.
687c478bd9Sstevel@tonic-gate * 3. tail part of new SACK blk overlaps with another blk.
697c478bd9Sstevel@tonic-gate * 4. head part of new SACK blk overlaps with another blk.
707c478bd9Sstevel@tonic-gate * 5. new SACK blk completely contains another blk.
717c478bd9Sstevel@tonic-gate *
727c478bd9Sstevel@tonic-gate * Use tmp to hold old SACK blks. After the loop, copy them back
737c478bd9Sstevel@tonic-gate * to head.
747c478bd9Sstevel@tonic-gate */
757c478bd9Sstevel@tonic-gate old_num = *num;
767c478bd9Sstevel@tonic-gate if (old_num > MAX_SACK_BLK - 1) {
777c478bd9Sstevel@tonic-gate old_num = MAX_SACK_BLK - 1;
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate new_num = old_num;
807c478bd9Sstevel@tonic-gate j = 0;
817c478bd9Sstevel@tonic-gate for (i = 0; i < old_num; i++) {
827c478bd9Sstevel@tonic-gate if (SEQ_LT(end, head[i].begin) || SEQ_GT(begin, head[i].end)) {
837c478bd9Sstevel@tonic-gate /* Case 1: continue to check. */
847c478bd9Sstevel@tonic-gate tmp[j].begin = head[i].begin;
857c478bd9Sstevel@tonic-gate tmp[j].end = head[i].end;
867c478bd9Sstevel@tonic-gate j++;
877c478bd9Sstevel@tonic-gate continue;
887c478bd9Sstevel@tonic-gate } else if (SEQ_GEQ(begin, head[i].begin) &&
897c478bd9Sstevel@tonic-gate SEQ_LEQ(end, head[i].end)) {
907c478bd9Sstevel@tonic-gate /* Case 2: re-insert the old blk to the head. */
917c478bd9Sstevel@tonic-gate begin = head[i].begin;
927c478bd9Sstevel@tonic-gate end = head[i].end;
937c478bd9Sstevel@tonic-gate } else if (SEQ_LEQ(end, head[i].end) &&
947c478bd9Sstevel@tonic-gate SEQ_GEQ(end, head[i].begin)) {
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate * Case 3: Extend the new blk, remove the old one
977c478bd9Sstevel@tonic-gate * and continue to check.
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate end = head[i].end;
1007c478bd9Sstevel@tonic-gate } else if (SEQ_GEQ(begin, head[i].begin) &&
1017c478bd9Sstevel@tonic-gate SEQ_LEQ(begin, head[i].end)) {
1027c478bd9Sstevel@tonic-gate /* Case 4 */
1037c478bd9Sstevel@tonic-gate begin = head[i].begin;
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate * Common code for all cases except the first one, which
1077c478bd9Sstevel@tonic-gate * copies the original SACK blk into the tmp storage. Other
1087c478bd9Sstevel@tonic-gate * cases remove the original SACK blk by not copying into
1097c478bd9Sstevel@tonic-gate * tmp storage.
1107c478bd9Sstevel@tonic-gate */
1117c478bd9Sstevel@tonic-gate new_num--;
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate head[0].begin = begin;
1157c478bd9Sstevel@tonic-gate head[0].end = end;
1167c478bd9Sstevel@tonic-gate for (i = 0; i < new_num; i++) {
1177c478bd9Sstevel@tonic-gate head[i+1].begin = tmp[i].begin;
1187c478bd9Sstevel@tonic-gate head[i+1].end = tmp[i].end;
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate *num = new_num + 1;
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate /*
1257c478bd9Sstevel@tonic-gate * To remove a SACK block.
1267c478bd9Sstevel@tonic-gate *
1277c478bd9Sstevel@tonic-gate * Parameters:
1287c478bd9Sstevel@tonic-gate * sack_blk_t *head: pointer to the array of SACK blks.
1297c478bd9Sstevel@tonic-gate * tcp_seq end: to remove all sack blk with seq num less than end.
1307c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of SACK blks in the array.
1317c478bd9Sstevel@tonic-gate */
1327c478bd9Sstevel@tonic-gate void
tcp_sack_remove(sack_blk_t * head,tcp_seq end,int32_t * num)1337c478bd9Sstevel@tonic-gate tcp_sack_remove(sack_blk_t *head, tcp_seq end, int32_t *num)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate sack_blk_t tmp[MAX_SACK_BLK];
1367c478bd9Sstevel@tonic-gate int32_t i, j, old_num, new_num;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (*num == 0)
1397c478bd9Sstevel@tonic-gate return;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate old_num = *num;
1427c478bd9Sstevel@tonic-gate new_num = old_num;
1437c478bd9Sstevel@tonic-gate j = 0;
1447c478bd9Sstevel@tonic-gate /* Walk thru the whole list and copy the new list to tmp[]. */
1457c478bd9Sstevel@tonic-gate for (i = 0; i < old_num; i++) {
1467c478bd9Sstevel@tonic-gate if (SEQ_GT(end, head[i].begin)) {
1477c478bd9Sstevel@tonic-gate /*
1487c478bd9Sstevel@tonic-gate * Check to see if the old SACK blk needs to be
1497c478bd9Sstevel@tonic-gate * removed or updated. If the old blk is just
1507c478bd9Sstevel@tonic-gate * partially covered, update begin and continue.
1517c478bd9Sstevel@tonic-gate * If the old blk is completely covered, remove it
1527c478bd9Sstevel@tonic-gate * and continue to check.
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate if (SEQ_GEQ(end, head[i].end)) {
1557c478bd9Sstevel@tonic-gate new_num--;
1567c478bd9Sstevel@tonic-gate continue;
1577c478bd9Sstevel@tonic-gate } else {
1587c478bd9Sstevel@tonic-gate tmp[j].begin = end;
1597c478bd9Sstevel@tonic-gate tmp[j].end = head[i].end;
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate } else {
1627c478bd9Sstevel@tonic-gate tmp[j].begin = head[i].begin;
1637c478bd9Sstevel@tonic-gate tmp[j].end = head[i].end;
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate j++;
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate /* Copy tmp[] back to the original list. */
1687c478bd9Sstevel@tonic-gate for (i = 0; i < new_num; i++) {
1697c478bd9Sstevel@tonic-gate head[i].begin = tmp[i].begin;
1707c478bd9Sstevel@tonic-gate head[i].end = tmp[i].end;
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate *num = new_num;
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * Use the SACK info to insert a "notsack'ed" blk. The notsack'ed blk list
1787c478bd9Sstevel@tonic-gate * contains the list of blks which have not been selectively acknowledged
1797c478bd9Sstevel@tonic-gate * by the receiver. The SACK info is a blk which is being selectively
1807c478bd9Sstevel@tonic-gate * acknowledged by the receiver.
1817c478bd9Sstevel@tonic-gate *
1827c478bd9Sstevel@tonic-gate * Parameters:
1837c478bd9Sstevel@tonic-gate * notsack_blk_t **head: address of the pointer to the list of notsack'ed
1847c478bd9Sstevel@tonic-gate * blks.
1857c478bd9Sstevel@tonic-gate * tcp_seq begin: starting seq num of the SACK info.
1867c478bd9Sstevel@tonic-gate * tcp_seq end: ending seq num of the SACK info.
1877c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of notsack'ed blk on the list.
1887c478bd9Sstevel@tonic-gate * uint32_t *sum: (referenced) total num of bytes of all the notsack'ed
1897c478bd9Sstevel@tonic-gate * blks.
1907c478bd9Sstevel@tonic-gate */
1917c478bd9Sstevel@tonic-gate void
tcp_notsack_insert(notsack_blk_t ** head,tcp_seq begin,tcp_seq end,int32_t * num,uint32_t * sum)1927c478bd9Sstevel@tonic-gate tcp_notsack_insert(notsack_blk_t **head, tcp_seq begin, tcp_seq end,
1937c478bd9Sstevel@tonic-gate int32_t *num, uint32_t *sum)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate notsack_blk_t *prev, *tmp, *new;
1967c478bd9Sstevel@tonic-gate uint32_t tmp_sum, tmp_num;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate if (*head == NULL) {
1997c478bd9Sstevel@tonic-gate return;
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate tmp = *head;
2037c478bd9Sstevel@tonic-gate prev = NULL;
2047c478bd9Sstevel@tonic-gate /* Find the right place of updating the list. */
2057c478bd9Sstevel@tonic-gate while ((tmp != NULL) && SEQ_LEQ(tmp->end, begin)) {
2067c478bd9Sstevel@tonic-gate prev = tmp;
2077c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++;
2087c478bd9Sstevel@tonic-gate tmp = tmp->next;
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate /*
2127c478bd9Sstevel@tonic-gate * This can happen only when TCP sends new data but the notsack list
2137c478bd9Sstevel@tonic-gate * is not updated.
2147c478bd9Sstevel@tonic-gate */
2157c478bd9Sstevel@tonic-gate if (tmp == NULL) {
2167c478bd9Sstevel@tonic-gate return;
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate * This means the new SACK info covers something that is not on
2217c478bd9Sstevel@tonic-gate * the list anymore.
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate if (SEQ_LEQ(end, tmp->begin)) {
2247c478bd9Sstevel@tonic-gate return;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate /* The SACK info covers up to this blk. So just check for this blk. */
2287c478bd9Sstevel@tonic-gate if (SEQ_LEQ(end, tmp->end)) {
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate * Only this notsack'ed blk is completely covered. Delete
2317c478bd9Sstevel@tonic-gate * it and return.
2327c478bd9Sstevel@tonic-gate */
2337c478bd9Sstevel@tonic-gate if (end == tmp->end && SEQ_LEQ(begin, tmp->begin)) {
2347c478bd9Sstevel@tonic-gate if (prev != NULL) {
2357c478bd9Sstevel@tonic-gate prev->next = tmp->next;
2367c478bd9Sstevel@tonic-gate } else {
2377c478bd9Sstevel@tonic-gate *head = tmp->next;
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate (*num)--;
2407c478bd9Sstevel@tonic-gate *sum -= tmp->end - tmp->begin;
241*66cd0f60SKacheong Poon kmem_cache_free(tcp_notsack_blk_cache, tmp);
2427c478bd9Sstevel@tonic-gate return;
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate /* This blk is partially covered. */
2457c478bd9Sstevel@tonic-gate if (SEQ_GEQ(begin, tmp->begin)) {
2467c478bd9Sstevel@tonic-gate /* Check what needs to be updated. */
2477c478bd9Sstevel@tonic-gate if (begin == tmp->begin) {
2487c478bd9Sstevel@tonic-gate *sum -= end - tmp->begin;
2497c478bd9Sstevel@tonic-gate tmp->begin = end;
2507c478bd9Sstevel@tonic-gate } else if (end == tmp->end) {
2517c478bd9Sstevel@tonic-gate *sum -= tmp->end - begin;
2527c478bd9Sstevel@tonic-gate tmp->end = begin;
2537c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++;
2547c478bd9Sstevel@tonic-gate } else {
2557c478bd9Sstevel@tonic-gate /* Split the notsack blk. */
256*66cd0f60SKacheong Poon if ((new = kmem_cache_alloc(
257*66cd0f60SKacheong Poon tcp_notsack_blk_cache, KM_NOSLEEP)) ==
258*66cd0f60SKacheong Poon NULL) {
2597c478bd9Sstevel@tonic-gate return;
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate new->end = tmp->end;
2627c478bd9Sstevel@tonic-gate new->begin = end;
2637c478bd9Sstevel@tonic-gate new->next = tmp->next;
2647c478bd9Sstevel@tonic-gate new->sack_cnt = 0;
2657c478bd9Sstevel@tonic-gate tmp->end = begin;
2667c478bd9Sstevel@tonic-gate tmp->next = new;
2677c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++;
2687c478bd9Sstevel@tonic-gate (*num)++;
2697c478bd9Sstevel@tonic-gate *sum -= end - begin;
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate } else {
2727c478bd9Sstevel@tonic-gate *sum -= end - tmp->begin;
2737c478bd9Sstevel@tonic-gate tmp->begin = end;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate return;
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate /* Need to check for coverage of this blk and later blks. */
2797c478bd9Sstevel@tonic-gate tmp_sum = *sum;
2807c478bd9Sstevel@tonic-gate tmp_num = *num;
2817c478bd9Sstevel@tonic-gate if (SEQ_LT(tmp->begin, begin)) {
2827c478bd9Sstevel@tonic-gate tmp_sum -= tmp->end - begin;
2837c478bd9Sstevel@tonic-gate tmp->end = begin;
2847c478bd9Sstevel@tonic-gate (tmp->sack_cnt)++;
2857c478bd9Sstevel@tonic-gate prev = tmp;
2867c478bd9Sstevel@tonic-gate tmp = tmp->next;
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate while (tmp != NULL) {
2907c478bd9Sstevel@tonic-gate /* The coverage stops here. */
2917c478bd9Sstevel@tonic-gate if (SEQ_GT(tmp->begin, end)) {
2927c478bd9Sstevel@tonic-gate break;
2937c478bd9Sstevel@tonic-gate } else {
2947c478bd9Sstevel@tonic-gate /* Is the blk completely or partially covered? */
2957c478bd9Sstevel@tonic-gate if (SEQ_LEQ(tmp->end, end)) {
2967c478bd9Sstevel@tonic-gate tmp_num--;
2977c478bd9Sstevel@tonic-gate tmp_sum -= tmp->end - tmp->begin;
2987c478bd9Sstevel@tonic-gate if (prev != NULL) {
2997c478bd9Sstevel@tonic-gate prev->next = tmp->next;
300*66cd0f60SKacheong Poon kmem_cache_free(tcp_notsack_blk_cache,
301*66cd0f60SKacheong Poon tmp);
3027c478bd9Sstevel@tonic-gate tmp = prev->next;
3037c478bd9Sstevel@tonic-gate } else {
3047c478bd9Sstevel@tonic-gate *head = tmp->next;
305*66cd0f60SKacheong Poon kmem_cache_free(tcp_notsack_blk_cache,
306*66cd0f60SKacheong Poon tmp);
3077c478bd9Sstevel@tonic-gate tmp = *head;
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate } else {
3107c478bd9Sstevel@tonic-gate /*
3117c478bd9Sstevel@tonic-gate * This blk is partially covered. It also
3127c478bd9Sstevel@tonic-gate * means it should be the end of coverage.
3137c478bd9Sstevel@tonic-gate */
3147c478bd9Sstevel@tonic-gate tmp_sum -= end - tmp->begin;
3157c478bd9Sstevel@tonic-gate tmp->begin = end;
3167c478bd9Sstevel@tonic-gate break;
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate *num = tmp_num;
3217c478bd9Sstevel@tonic-gate *sum = tmp_sum;
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * To remove notsack'ed blks.
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate * Parameters:
3297c478bd9Sstevel@tonic-gate * notsack_blk_t **head: address of the pointer to the list of notsack'ed
3307c478bd9Sstevel@tonic-gate * blks.
3317c478bd9Sstevel@tonic-gate * tcp_seq end: to remove all notsack'ed blk with seq num less than end.
3327c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of notsack'ed blks.
3337c478bd9Sstevel@tonic-gate * uint32_t *sum: (referenced) total num of bytes of all the notsack'ed
3347c478bd9Sstevel@tonic-gate * blks.
3357c478bd9Sstevel@tonic-gate */
3367c478bd9Sstevel@tonic-gate void
tcp_notsack_remove(notsack_blk_t ** head,tcp_seq end,int32_t * num,uint32_t * sum)3377c478bd9Sstevel@tonic-gate tcp_notsack_remove(notsack_blk_t **head, tcp_seq end, int32_t *num,
3387c478bd9Sstevel@tonic-gate uint32_t *sum)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate notsack_blk_t *prev, *tmp;
3417c478bd9Sstevel@tonic-gate uint32_t tmp_sum = *sum;
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate if (*head == NULL)
3447c478bd9Sstevel@tonic-gate return;
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate prev = NULL;
3477c478bd9Sstevel@tonic-gate tmp = *head;
3487c478bd9Sstevel@tonic-gate while (tmp != NULL) {
3497c478bd9Sstevel@tonic-gate /* There is nothing to discard. */
3507c478bd9Sstevel@tonic-gate if (SEQ_GT(tmp->begin, end)) {
3517c478bd9Sstevel@tonic-gate break;
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate /* Is the blk completely or partially covered? */
3557c478bd9Sstevel@tonic-gate if (SEQ_GEQ(end, tmp->end)) {
3567c478bd9Sstevel@tonic-gate (*num)--;
3577c478bd9Sstevel@tonic-gate tmp_sum -= tmp->end - tmp->begin;
3587c478bd9Sstevel@tonic-gate if (prev == NULL) {
3597c478bd9Sstevel@tonic-gate *head = tmp->next;
360*66cd0f60SKacheong Poon kmem_cache_free(tcp_notsack_blk_cache, tmp);
3617c478bd9Sstevel@tonic-gate tmp = *head;
3627c478bd9Sstevel@tonic-gate } else {
3637c478bd9Sstevel@tonic-gate prev->next = tmp->next;
364*66cd0f60SKacheong Poon kmem_cache_free(tcp_notsack_blk_cache, tmp);
3657c478bd9Sstevel@tonic-gate tmp = prev->next;
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate } else {
3687c478bd9Sstevel@tonic-gate tmp_sum -= end - tmp->begin;
3697c478bd9Sstevel@tonic-gate tmp->begin = end;
3707c478bd9Sstevel@tonic-gate break;
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate *sum = tmp_sum;
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * To update the notsack'ed list when new data is sent.
3797c478bd9Sstevel@tonic-gate *
3807c478bd9Sstevel@tonic-gate * Assumption: this should only be called when new notsack blk is to be added.
3817c478bd9Sstevel@tonic-gate *
3827c478bd9Sstevel@tonic-gate * Parameters:
3837c478bd9Sstevel@tonic-gate * notsack_blk_t **head: address of the pointer to the list of notsack'ed
3847c478bd9Sstevel@tonic-gate * blks.
3857c478bd9Sstevel@tonic-gate * tcp_seq begin: beginning seq num of new data.
3867c478bd9Sstevel@tonic-gate * tcp_seq end: ending seq num of new data.
3877c478bd9Sstevel@tonic-gate * int32_t *num: (referenced) total num of notsack'ed blks.
3887c478bd9Sstevel@tonic-gate * uint32_t *sum: (referenced) total num of bytes of all the notsack'ed
3897c478bd9Sstevel@tonic-gate * blks.
3907c478bd9Sstevel@tonic-gate */
tcp_notsack_update(notsack_blk_t ** head,tcp_seq begin,tcp_seq end,int32_t * num,uint32_t * sum)3917c478bd9Sstevel@tonic-gate void tcp_notsack_update(notsack_blk_t **head, tcp_seq begin, tcp_seq end,
3927c478bd9Sstevel@tonic-gate int32_t *num, uint32_t *sum)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate notsack_blk_t *tmp;
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate tmp = *head;
3977c478bd9Sstevel@tonic-gate /* If the list is empty, create a new one. */
3987c478bd9Sstevel@tonic-gate if (tmp == NULL) {
399*66cd0f60SKacheong Poon if ((tmp = kmem_cache_alloc(tcp_notsack_blk_cache,
400*66cd0f60SKacheong Poon KM_NOSLEEP)) == NULL) {
4017c478bd9Sstevel@tonic-gate return;
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate tmp->begin = begin;
4047c478bd9Sstevel@tonic-gate tmp->end = end;
4057c478bd9Sstevel@tonic-gate tmp->next = NULL;
4067c478bd9Sstevel@tonic-gate tmp->sack_cnt = 0;
4077c478bd9Sstevel@tonic-gate *head = tmp;
4087c478bd9Sstevel@tonic-gate *num = 1;
4097c478bd9Sstevel@tonic-gate *sum = end - begin;
4107c478bd9Sstevel@tonic-gate return;
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate * Find the place to add the new blk. This assumes that new data
4157c478bd9Sstevel@tonic-gate * is being sent, so the place to insert the new notsack blk is at
4167c478bd9Sstevel@tonic-gate * the end of the list.
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate while (tmp->next != NULL) {
4197c478bd9Sstevel@tonic-gate tmp = tmp->next;
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /* Does the new blk overlap with old one? */
4237c478bd9Sstevel@tonic-gate if (SEQ_GEQ(tmp->end, begin)) {
4247c478bd9Sstevel@tonic-gate *sum += end - tmp->end;
4257c478bd9Sstevel@tonic-gate tmp->end = end;
4267c478bd9Sstevel@tonic-gate } else {
4277c478bd9Sstevel@tonic-gate /* No. Need to create a new notsack blk. */
428*66cd0f60SKacheong Poon tmp->next = kmem_cache_alloc(tcp_notsack_blk_cache, KM_NOSLEEP);
4297c478bd9Sstevel@tonic-gate if (tmp->next != NULL) {
4307c478bd9Sstevel@tonic-gate tmp = tmp->next;
4317c478bd9Sstevel@tonic-gate tmp->begin = begin;
4327c478bd9Sstevel@tonic-gate tmp->end = end;
4337c478bd9Sstevel@tonic-gate tmp->next = NULL;
4347c478bd9Sstevel@tonic-gate tmp->sack_cnt = 0;
4357c478bd9Sstevel@tonic-gate (*num)++;
4367c478bd9Sstevel@tonic-gate *sum += end - begin;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate }
440