Home | History | Annotate | Line # | Download | only in netinet
tcp_sack.c revision 1.32
      1  1.32     pooka /* $NetBSD: tcp_sack.c,v 1.32 2015/08/24 22:21:26 pooka Exp $ */
      2   1.1  jonathan 
      3   1.1  jonathan /*
      4   1.1  jonathan  * Copyright (c) 2005 The NetBSD Foundation, Inc.
      5   1.1  jonathan  * All rights reserved.
      6   1.1  jonathan  *
      7   1.1  jonathan  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1  jonathan  * by Kentaro A. Kurahone.
      9   1.1  jonathan  *
     10   1.1  jonathan  * Redistribution and use in source and binary forms, with or without
     11   1.1  jonathan  * modification, are permitted provided that the following conditions
     12   1.1  jonathan  * are met:
     13   1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
     14   1.1  jonathan  *    notice, this list of conditions and the following disclaimer.
     15   1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  jonathan  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  jonathan  *    documentation and/or other materials provided with the distribution.
     18   1.1  jonathan  *
     19   1.1  jonathan  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1  jonathan  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1  jonathan  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1  jonathan  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1  jonathan  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1  jonathan  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1  jonathan  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1  jonathan  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1  jonathan  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1  jonathan  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1  jonathan  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1  jonathan  */
     31   1.1  jonathan 
     32   1.1  jonathan /*
     33   1.1  jonathan  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
     34   1.1  jonathan  *	The Regents of the University of California.  All rights reserved.
     35   1.1  jonathan  *
     36   1.1  jonathan  * Redistribution and use in source and binary forms, with or without
     37   1.1  jonathan  * modification, are permitted provided that the following conditions
     38   1.1  jonathan  * are met:
     39   1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
     40   1.1  jonathan  *    notice, this list of conditions and the following disclaimer.
     41   1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     42   1.1  jonathan  *    notice, this list of conditions and the following disclaimer in the
     43   1.1  jonathan  *    documentation and/or other materials provided with the distribution.
     44   1.1  jonathan  * 4. Neither the name of the University nor the names of its contributors
     45   1.1  jonathan  *    may be used to endorse or promote products derived from this software
     46   1.1  jonathan  *    without specific prior written permission.
     47   1.1  jonathan  *
     48   1.1  jonathan  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     49   1.1  jonathan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     50   1.1  jonathan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     51   1.1  jonathan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     52   1.1  jonathan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     53   1.1  jonathan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     54   1.1  jonathan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     55   1.1  jonathan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     56   1.1  jonathan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     57   1.1  jonathan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     58   1.1  jonathan  * SUCH DAMAGE.
     59   1.1  jonathan  *
     60   1.1  jonathan  *	@(#)tcp_sack.c	8.12 (Berkeley) 5/24/95
     61   1.1  jonathan  * $FreeBSD: src/sys/netinet/tcp_sack.c,v 1.3.2.2 2004/12/25 23:02:57 rwatson Exp $
     62   1.1  jonathan  */
     63   1.1  jonathan 
     64   1.1  jonathan /*
     65   1.1  jonathan  *	@@(#)COPYRIGHT	1.1 (NRL) 17 January 1995
     66   1.1  jonathan  *
     67   1.1  jonathan  * NRL grants permission for redistribution and use in source and binary
     68   1.1  jonathan  * forms, with or without modification, of the software and documentation
     69   1.1  jonathan  * created at NRL provided that the following conditions are met:
     70   1.1  jonathan  *
     71   1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
     72   1.1  jonathan  *    notice, this list of conditions and the following disclaimer.
     73   1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     74   1.1  jonathan  *    notice, this list of conditions and the following disclaimer in the
     75   1.1  jonathan  *    documentation and/or other materials provided with the distribution.
     76   1.1  jonathan  * 3. All advertising materials mentioning features or use of this software
     77   1.1  jonathan  *    must display the following acknowledgements:
     78   1.1  jonathan  *	This product includes software developed by the University of
     79   1.1  jonathan  *	California, Berkeley and its contributors.
     80   1.1  jonathan  *	This product includes software developed at the Information
     81   1.1  jonathan  *	Technology Division, US Naval Research Laboratory.
     82   1.1  jonathan  * 4. Neither the name of the NRL nor the names of its contributors
     83   1.1  jonathan  *    may be used to endorse or promote products derived from this software
     84   1.1  jonathan  *    without specific prior written permission.
     85   1.1  jonathan  *
     86   1.1  jonathan  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
     87   1.1  jonathan  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     88   1.1  jonathan  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     89   1.1  jonathan  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
     90   1.1  jonathan  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     91   1.1  jonathan  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     92   1.1  jonathan  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     93   1.1  jonathan  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     94   1.1  jonathan  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     95   1.1  jonathan  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     96   1.1  jonathan  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     97   1.1  jonathan  *
     98   1.1  jonathan  * The views and conclusions contained in the software and documentation
     99   1.1  jonathan  * are those of the authors and should not be interpreted as representing
    100   1.1  jonathan  * official policies, either expressed or implied, of the US Naval
    101   1.1  jonathan  * Research Laboratory (NRL).
    102   1.1  jonathan  */
    103   1.1  jonathan 
    104   1.1  jonathan #include <sys/cdefs.h>
    105  1.32     pooka __KERNEL_RCSID(0, "$NetBSD: tcp_sack.c,v 1.32 2015/08/24 22:21:26 pooka Exp $");
    106   1.1  jonathan 
    107  1.32     pooka #ifdef _KERNEL_OPT
    108   1.1  jonathan #include "opt_inet.h"
    109   1.1  jonathan #include "opt_inet_csum.h"
    110   1.1  jonathan #include "opt_tcp_debug.h"
    111  1.22      yamt #include "opt_ddb.h"
    112  1.32     pooka #endif
    113   1.1  jonathan 
    114   1.1  jonathan #include <sys/param.h>
    115   1.1  jonathan #include <sys/systm.h>
    116   1.1  jonathan #include <sys/mbuf.h>
    117   1.1  jonathan #include <sys/protosw.h>
    118   1.1  jonathan #include <sys/socket.h>
    119   1.1  jonathan #include <sys/socketvar.h>
    120   1.1  jonathan #include <sys/errno.h>
    121   1.1  jonathan #include <sys/syslog.h>
    122   1.1  jonathan #include <sys/pool.h>
    123   1.1  jonathan #include <sys/domain.h>
    124   1.1  jonathan #include <sys/kernel.h>
    125   1.1  jonathan 
    126   1.1  jonathan #include <net/if.h>
    127   1.1  jonathan #include <net/route.h>
    128   1.1  jonathan #include <net/if_types.h>
    129   1.1  jonathan 
    130   1.1  jonathan #include <netinet/in.h>
    131   1.1  jonathan #include <netinet/in_systm.h>
    132   1.1  jonathan #include <netinet/ip.h>
    133   1.1  jonathan #include <netinet/in_pcb.h>
    134   1.1  jonathan #include <netinet/in_var.h>
    135   1.1  jonathan #include <netinet/ip_var.h>
    136   1.1  jonathan 
    137   1.1  jonathan #ifdef INET6
    138   1.1  jonathan #ifndef INET
    139   1.1  jonathan #include <netinet/in.h>
    140   1.1  jonathan #endif
    141   1.1  jonathan #include <netinet/ip6.h>
    142   1.1  jonathan #include <netinet6/ip6_var.h>
    143   1.1  jonathan #include <netinet6/in6_pcb.h>
    144   1.1  jonathan #include <netinet6/ip6_var.h>
    145   1.1  jonathan #include <netinet6/in6_var.h>
    146   1.1  jonathan #include <netinet/icmp6.h>
    147   1.1  jonathan #include <netinet6/nd6.h>
    148   1.1  jonathan #endif
    149   1.1  jonathan 
    150   1.1  jonathan #ifndef INET6
    151   1.1  jonathan /* always need ip6.h for IP6_EXTHDR_GET */
    152   1.1  jonathan #include <netinet/ip6.h>
    153   1.1  jonathan #endif
    154   1.1  jonathan 
    155   1.1  jonathan #include <netinet/tcp.h>
    156   1.1  jonathan #include <netinet/tcp_fsm.h>
    157   1.1  jonathan #include <netinet/tcp_seq.h>
    158   1.1  jonathan #include <netinet/tcp_timer.h>
    159   1.1  jonathan #include <netinet/tcp_var.h>
    160   1.1  jonathan #include <netinet/tcpip.h>
    161   1.1  jonathan #include <netinet/tcp_debug.h>
    162   1.1  jonathan 
    163   1.1  jonathan /* SACK block pool. */
    164  1.25     pooka static struct pool sackhole_pool;
    165  1.25     pooka 
    166  1.25     pooka void
    167  1.28      matt tcp_sack_init(void)
    168  1.25     pooka {
    169  1.25     pooka 
    170  1.25     pooka 	pool_init(&sackhole_pool, sizeof(struct sackhole), 0, 0, 0,
    171  1.25     pooka 	    "sackholepl", NULL, IPL_SOFTNET);
    172  1.25     pooka }
    173  1.19      yamt 
    174  1.19      yamt static struct sackhole *
    175  1.19      yamt sack_allochole(struct tcpcb *tp)
    176  1.19      yamt {
    177  1.19      yamt 	struct sackhole *hole;
    178  1.19      yamt 
    179  1.19      yamt 	if (tp->snd_numholes >= tcp_sack_tp_maxholes ||
    180  1.19      yamt 	    tcp_sack_globalholes >= tcp_sack_globalmaxholes) {
    181  1.19      yamt 		return NULL;
    182  1.19      yamt 	}
    183  1.19      yamt 	hole = pool_get(&sackhole_pool, PR_NOWAIT);
    184  1.19      yamt 	if (hole == NULL) {
    185  1.19      yamt 		return NULL;
    186  1.19      yamt 	}
    187  1.19      yamt 	tp->snd_numholes++;
    188  1.19      yamt 	tcp_sack_globalholes++;
    189  1.19      yamt 
    190  1.19      yamt 	return hole;
    191  1.19      yamt }
    192  1.19      yamt 
    193  1.19      yamt static struct sackhole *
    194  1.19      yamt sack_inserthole(struct tcpcb *tp, tcp_seq start, tcp_seq end,
    195  1.19      yamt     struct sackhole *prev)
    196  1.19      yamt {
    197  1.19      yamt 	struct sackhole *hole;
    198  1.19      yamt 
    199  1.19      yamt 	hole = sack_allochole(tp);
    200  1.19      yamt 	if (hole == NULL) {
    201  1.19      yamt 		return NULL;
    202  1.19      yamt 	}
    203  1.19      yamt 	hole->start = hole->rxmit = start;
    204  1.19      yamt 	hole->end = end;
    205  1.19      yamt 	if (prev != NULL) {
    206  1.19      yamt 		TAILQ_INSERT_AFTER(&tp->snd_holes, prev, hole, sackhole_q);
    207  1.19      yamt 	} else {
    208  1.19      yamt 		TAILQ_INSERT_TAIL(&tp->snd_holes, hole, sackhole_q);
    209  1.19      yamt 	}
    210  1.19      yamt 	return hole;
    211  1.19      yamt }
    212  1.19      yamt 
    213  1.19      yamt static struct sackhole *
    214  1.19      yamt sack_removehole(struct tcpcb *tp, struct sackhole *hole)
    215  1.19      yamt {
    216  1.19      yamt 	struct sackhole *next;
    217  1.19      yamt 
    218  1.19      yamt 	next = TAILQ_NEXT(hole, sackhole_q);
    219  1.19      yamt 	tp->snd_numholes--;
    220  1.19      yamt 	tcp_sack_globalholes--;
    221  1.19      yamt 	TAILQ_REMOVE(&tp->snd_holes, hole, sackhole_q);
    222  1.19      yamt 	pool_put(&sackhole_pool, hole);
    223  1.19      yamt 
    224  1.19      yamt 	return next;
    225  1.19      yamt }
    226   1.1  jonathan 
    227  1.26      yamt /*
    228  1.26      yamt  * tcp_new_dsack: record the reception of a duplicated segment.
    229  1.26      yamt  */
    230  1.26      yamt 
    231   1.1  jonathan void
    232   1.1  jonathan tcp_new_dsack(struct tcpcb *tp, tcp_seq seq, u_int32_t len)
    233   1.1  jonathan {
    234  1.26      yamt 
    235   1.1  jonathan 	if (TCP_SACK_ENABLED(tp)) {
    236   1.1  jonathan 		tp->rcv_dsack_block.left = seq;
    237   1.1  jonathan 		tp->rcv_dsack_block.right = seq + len;
    238   1.1  jonathan 		tp->rcv_sack_flags |= TCPSACK_HAVED;
    239   1.1  jonathan 	}
    240   1.1  jonathan }
    241   1.1  jonathan 
    242  1.26      yamt /*
    243  1.26      yamt  * tcp_sack_option: parse the given SACK option and update the scoreboard.
    244  1.26      yamt  */
    245  1.26      yamt 
    246   1.1  jonathan void
    247  1.21      yamt tcp_sack_option(struct tcpcb *tp, const struct tcphdr *th, const u_char *cp,
    248  1.21      yamt     int optlen)
    249   1.1  jonathan {
    250   1.5      yamt 	struct sackblk
    251   1.5      yamt 	    t_sack_block[(MAX_TCPOPTLEN - 2) / (sizeof(u_int32_t) * 2)];
    252   1.1  jonathan 	struct sackblk *sack = NULL;
    253   1.1  jonathan 	struct sackhole *cur = NULL;
    254   1.1  jonathan 	struct sackhole *tmp = NULL;
    255  1.21      yamt 	const char *lp = cp + 2;
    256  1.18      yamt 	int i, j, num_sack_blks;
    257   1.1  jonathan 	tcp_seq left, right, acked;
    258   1.1  jonathan 
    259   1.1  jonathan 	/*
    260  1.11  kurahone 	 * If we aren't processing SACK responses, this is not an ACK
    261  1.11  kurahone 	 * or the peer sends us a sack option with invalid length, don't
    262   1.1  jonathan 	 * update the scoreboard.
    263   1.1  jonathan 	 */
    264  1.11  kurahone 	if (!TCP_SACK_ENABLED(tp) || ((th->th_flags & TH_ACK) == 0) ||
    265  1.11  kurahone 			(optlen % 8 != 2 || optlen < 10)) {
    266   1.1  jonathan 		return;
    267   1.1  jonathan 	}
    268   1.1  jonathan 
    269  1.12  kurahone 	/*
    270  1.12  kurahone 	 * If we don't want any SACK holes to be allocated, just return.
    271  1.12  kurahone 	 */
    272  1.12  kurahone 	if (tcp_sack_globalmaxholes == 0 || tcp_sack_tp_maxholes == 0) {
    273  1.12  kurahone 		return;
    274  1.12  kurahone 	}
    275  1.12  kurahone 
    276  1.11  kurahone 	/* If the ACK is outside [snd_una, snd_max], ignore the SACK options. */
    277  1.11  kurahone 	if (SEQ_LT(th->th_ack, tp->snd_una) || SEQ_GT(th->th_ack, tp->snd_max))
    278  1.11  kurahone 		return;
    279  1.11  kurahone 
    280   1.1  jonathan 	/*
    281   1.1  jonathan 	 * Extract SACK blocks.
    282   1.1  jonathan 	 *
    283   1.1  jonathan 	 * Note that t_sack_block is sorted so that we only need to do
    284   1.1  jonathan 	 * one pass over the sequence number space. (SACK "fast-path")
    285   1.1  jonathan 	 */
    286   1.1  jonathan 	num_sack_blks = optlen / 8;
    287   1.1  jonathan 	acked = (SEQ_GT(th->th_ack, tp->snd_una)) ? th->th_ack : tp->snd_una;
    288  1.20   reinoud 	for (i = 0; i < num_sack_blks; i++, lp += sizeof(uint32_t) * 2) {
    289  1.20   reinoud 		memcpy(&left, lp, sizeof(uint32_t));
    290  1.20   reinoud 		memcpy(&right, lp + sizeof(uint32_t), sizeof(uint32_t));
    291   1.3      yamt 		left = ntohl(left);
    292   1.3      yamt 		right = ntohl(right);
    293   1.1  jonathan 
    294  1.13      yamt 		if (SEQ_LEQ(right, acked) || SEQ_GT(right, tp->snd_max) ||
    295   1.4      yamt 		    SEQ_GEQ(left, right)) {
    296   1.1  jonathan 			/* SACK entry that's old, or invalid. */
    297   1.1  jonathan 			i--;
    298   1.1  jonathan 			num_sack_blks--;
    299   1.1  jonathan 			continue;
    300   1.1  jonathan 		}
    301   1.1  jonathan 
    302   1.1  jonathan 		/* Insertion sort. */
    303   1.2      yamt 		for (j = i; (j > 0) && SEQ_LT(left, t_sack_block[j - 1].left);
    304   1.2      yamt 		    j--) {
    305   1.1  jonathan 			t_sack_block[j].left = t_sack_block[j - 1].left;
    306   1.1  jonathan 			t_sack_block[j].right = t_sack_block[j - 1].right;
    307   1.1  jonathan 		}
    308   1.1  jonathan 		t_sack_block[j].left = left;
    309   1.1  jonathan 		t_sack_block[j].right = right;
    310   1.1  jonathan 	}
    311   1.1  jonathan 
    312   1.1  jonathan 	/* Update the scoreboard. */
    313   1.1  jonathan 	cur = TAILQ_FIRST(&tp->snd_holes);
    314   1.1  jonathan 	for (i = 0; i < num_sack_blks; i++) {
    315   1.1  jonathan 		sack = &t_sack_block[i];
    316   1.1  jonathan 		/*
    317   1.1  jonathan 		 * FACK TCP.  Update snd_fack so we can enter Fast
    318   1.1  jonathan 		 * Recovery early.
    319   1.1  jonathan 		 */
    320   1.1  jonathan 		if (SEQ_GEQ(sack->right, tp->snd_fack))
    321   1.1  jonathan 			tp->snd_fack = sack->right;
    322   1.1  jonathan 
    323   1.1  jonathan 		if (TAILQ_EMPTY(&tp->snd_holes)) {
    324   1.1  jonathan 			/* First hole. */
    325  1.19      yamt 			cur = sack_inserthole(tp, th->th_ack, sack->left, NULL);
    326   1.1  jonathan 			if (cur == NULL) {
    327   1.1  jonathan 				/* ENOBUFS, bail out*/
    328   1.1  jonathan 				return;
    329   1.1  jonathan 			}
    330   1.1  jonathan 			tp->rcv_lastsack = sack->right;
    331   1.1  jonathan 			continue; /* With next sack block */
    332   1.1  jonathan 		}
    333   1.1  jonathan 
    334   1.1  jonathan 		/* Go through the list of holes. */
    335   1.1  jonathan 		while (cur) {
    336   1.6      yamt 			if (SEQ_LEQ(sack->right, cur->start))
    337   1.1  jonathan 				/* SACKs data before the current hole */
    338   1.1  jonathan 				break; /* No use going through more holes */
    339   1.1  jonathan 
    340   1.1  jonathan 			if (SEQ_GEQ(sack->left, cur->end)) {
    341   1.1  jonathan 				/* SACKs data beyond the current hole */
    342   1.1  jonathan 				cur = TAILQ_NEXT(cur, sackhole_q);
    343   1.1  jonathan 				continue;
    344   1.1  jonathan 			}
    345   1.1  jonathan 
    346   1.1  jonathan 			if (SEQ_LEQ(sack->left, cur->start)) {
    347   1.1  jonathan 				/* Data acks at least the beginning of hole */
    348   1.1  jonathan 				if (SEQ_GEQ(sack->right, cur->end)) {
    349   1.1  jonathan 					/* Acks entire hole, so delete hole */
    350  1.19      yamt 					cur = sack_removehole(tp, cur);
    351   1.1  jonathan 					break;
    352   1.1  jonathan 				}
    353   1.1  jonathan 
    354   1.1  jonathan 				/* Otherwise, move start of hole forward */
    355   1.1  jonathan 				cur->start = sack->right;
    356   1.1  jonathan 				cur->rxmit = SEQ_MAX(cur->rxmit, cur->start);
    357   1.1  jonathan 				break;
    358   1.1  jonathan 			}
    359   1.1  jonathan 
    360   1.1  jonathan 			if (SEQ_GEQ(sack->right, cur->end)) {
    361   1.1  jonathan 				/* Move end of hole backward. */
    362   1.1  jonathan 				cur->end = sack->left;
    363   1.1  jonathan 				cur->rxmit = SEQ_MIN(cur->rxmit, cur->end);
    364   1.1  jonathan 				cur = TAILQ_NEXT(cur, sackhole_q);
    365   1.1  jonathan 				break;
    366   1.1  jonathan 			}
    367   1.1  jonathan 
    368   1.1  jonathan 			if (SEQ_LT(cur->start, sack->left) &&
    369   1.1  jonathan 			    SEQ_GT(cur->end, sack->right)) {
    370   1.1  jonathan 				/*
    371   1.1  jonathan 				 * ACKs some data in middle of a hole; need to
    372   1.1  jonathan 				 * split current hole
    373   1.1  jonathan 				 */
    374  1.19      yamt 				tmp = sack_inserthole(tp, sack->right, cur->end,
    375  1.19      yamt 				    cur);
    376   1.1  jonathan 				if (tmp == NULL) {
    377   1.1  jonathan 					return;
    378   1.1  jonathan 				}
    379   1.1  jonathan 				tmp->rxmit = SEQ_MAX(cur->rxmit, tmp->start);
    380   1.1  jonathan 				cur->end = sack->left;
    381   1.1  jonathan 				cur->rxmit = SEQ_MIN(cur->rxmit, cur->end);
    382   1.7      yamt 				cur = tmp;
    383   1.1  jonathan 				break;
    384   1.1  jonathan 			}
    385   1.1  jonathan 		}
    386   1.1  jonathan 
    387   1.1  jonathan 		/* At this point, we have reached the tail of the list. */
    388   1.1  jonathan 		if (SEQ_LT(tp->rcv_lastsack, sack->left)) {
    389   1.1  jonathan 			/*
    390   1.1  jonathan 			 * Need to append new hole at end.
    391   1.1  jonathan 			 */
    392  1.19      yamt 			cur = sack_inserthole(tp, tp->rcv_lastsack, sack->left,
    393  1.19      yamt 			    NULL);
    394  1.19      yamt 			if (cur == NULL) {
    395  1.12  kurahone 				return;
    396  1.12  kurahone 			}
    397   1.1  jonathan 		}
    398   1.8      yamt 		if (SEQ_LT(tp->rcv_lastsack, sack->right)) {
    399   1.8      yamt 			tp->rcv_lastsack = sack->right;
    400   1.8      yamt 		}
    401   1.1  jonathan 	}
    402   1.1  jonathan }
    403   1.1  jonathan 
    404  1.26      yamt /*
    405  1.26      yamt  * tcp_del_sackholes: remove holes covered by a cumulative ACK.
    406  1.26      yamt  */
    407  1.26      yamt 
    408   1.1  jonathan void
    409  1.21      yamt tcp_del_sackholes(struct tcpcb *tp, const struct tcphdr *th)
    410   1.1  jonathan {
    411   1.1  jonathan 	/* Max because this could be an older ack that just arrived. */
    412   1.1  jonathan 	tcp_seq lastack = SEQ_GT(th->th_ack, tp->snd_una) ?
    413   1.1  jonathan 		th->th_ack : tp->snd_una;
    414   1.1  jonathan 	struct sackhole *cur = TAILQ_FIRST(&tp->snd_holes);
    415   1.1  jonathan 
    416   1.1  jonathan 	while (cur) {
    417   1.1  jonathan 		if (SEQ_LEQ(cur->end, lastack)) {
    418  1.19      yamt 			cur = sack_removehole(tp, cur);
    419   1.1  jonathan 		} else if (SEQ_LT(cur->start, lastack)) {
    420   1.1  jonathan 			cur->start = lastack;
    421   1.1  jonathan 			if (SEQ_LT(cur->rxmit, cur->start))
    422   1.1  jonathan 				cur->rxmit = cur->start;
    423   1.1  jonathan 			break;
    424   1.1  jonathan 		} else
    425   1.1  jonathan 			break;
    426   1.1  jonathan 	}
    427   1.1  jonathan }
    428   1.1  jonathan 
    429  1.26      yamt /*
    430  1.26      yamt  * tcp_free_sackholes: clear the scoreboard.
    431  1.26      yamt  */
    432  1.26      yamt 
    433   1.1  jonathan void
    434   1.1  jonathan tcp_free_sackholes(struct tcpcb *tp)
    435   1.1  jonathan {
    436   1.1  jonathan 	struct sackhole *sack;
    437   1.1  jonathan 
    438   1.1  jonathan 	/* Free up the SACK hole list. */
    439  1.19      yamt 	while ((sack = TAILQ_FIRST(&tp->snd_holes)) != NULL) {
    440  1.19      yamt 		sack_removehole(tp, sack);
    441   1.1  jonathan 	}
    442  1.19      yamt 	KASSERT(tp->snd_numholes == 0);
    443   1.1  jonathan }
    444   1.1  jonathan 
    445   1.1  jonathan /*
    446   1.1  jonathan  * Returns pointer to a sackhole if there are any pending retransmissions;
    447   1.1  jonathan  * NULL otherwise.
    448   1.1  jonathan  */
    449   1.1  jonathan struct sackhole *
    450   1.1  jonathan tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt)
    451   1.1  jonathan {
    452   1.1  jonathan 	struct sackhole *cur = NULL;
    453   1.1  jonathan 
    454  1.17      yamt 	if (!TCP_SACK_ENABLED(tp))
    455   1.1  jonathan 		return (NULL);
    456   1.1  jonathan 
    457   1.1  jonathan 	*sack_bytes_rexmt = 0;
    458   1.1  jonathan 	TAILQ_FOREACH(cur, &tp->snd_holes, sackhole_q) {
    459   1.1  jonathan 		if (SEQ_LT(cur->rxmit, cur->end)) {
    460   1.2      yamt 			if (SEQ_LT(cur->rxmit, tp->snd_una)) {
    461   1.2      yamt 				/* old SACK hole */
    462   1.1  jonathan 				continue;
    463   1.1  jonathan 			}
    464   1.1  jonathan 			*sack_bytes_rexmt += (cur->rxmit - cur->start);
    465   1.1  jonathan 			break;
    466   1.1  jonathan 		}
    467   1.1  jonathan 		*sack_bytes_rexmt += (cur->rxmit - cur->start);
    468   1.1  jonathan 	}
    469   1.1  jonathan 
    470   1.1  jonathan 	return (cur);
    471   1.1  jonathan }
    472   1.1  jonathan 
    473   1.1  jonathan /*
    474   1.1  jonathan  * After a timeout, the SACK list may be rebuilt.  This SACK information
    475   1.1  jonathan  * should be used to avoid retransmitting SACKed data.  This function
    476   1.1  jonathan  * traverses the SACK list to see if snd_nxt should be moved forward.
    477   1.1  jonathan  */
    478   1.1  jonathan void
    479   1.1  jonathan tcp_sack_adjust(struct tcpcb *tp)
    480   1.1  jonathan {
    481   1.1  jonathan 	struct sackhole *cur = TAILQ_FIRST(&tp->snd_holes);
    482   1.1  jonathan 	struct sackhole *n = NULL;
    483   1.1  jonathan 
    484   1.1  jonathan 	if (TAILQ_EMPTY(&tp->snd_holes))
    485   1.1  jonathan 		return; /* No holes */
    486   1.1  jonathan 	if (SEQ_GEQ(tp->snd_nxt, tp->rcv_lastsack))
    487   1.1  jonathan 		return; /* We're already beyond any SACKed blocks */
    488   1.1  jonathan 
    489   1.1  jonathan 	/*
    490   1.1  jonathan 	 * Two cases for which we want to advance snd_nxt:
    491   1.1  jonathan 	 * i) snd_nxt lies between end of one hole and beginning of another
    492   1.1  jonathan 	 * ii) snd_nxt lies between end of last hole and rcv_lastsack
    493   1.1  jonathan 	 */
    494   1.1  jonathan 	while ((n = TAILQ_NEXT(cur, sackhole_q)) != NULL) {
    495   1.1  jonathan 		if (SEQ_LT(tp->snd_nxt, cur->end))
    496   1.1  jonathan 			return;
    497   1.1  jonathan 		if (SEQ_GEQ(tp->snd_nxt, n->start))
    498   1.1  jonathan 			cur = n;
    499   1.1  jonathan 		else {
    500   1.1  jonathan 			tp->snd_nxt = n->start;
    501   1.1  jonathan 			return;
    502   1.1  jonathan 		}
    503   1.1  jonathan 	}
    504   1.1  jonathan 	if (SEQ_LT(tp->snd_nxt, cur->end))
    505   1.1  jonathan 		return;
    506   1.1  jonathan 	tp->snd_nxt = tp->rcv_lastsack;
    507   1.1  jonathan 
    508   1.1  jonathan 	return;
    509   1.1  jonathan }
    510   1.9      yamt 
    511  1.26      yamt /*
    512  1.26      yamt  * tcp_sack_numblks: return the number of SACK blocks to send.
    513  1.26      yamt  */
    514  1.26      yamt 
    515   1.9      yamt int
    516  1.10      yamt tcp_sack_numblks(const struct tcpcb *tp)
    517   1.9      yamt {
    518  1.10      yamt 	int numblks;
    519   1.9      yamt 
    520  1.10      yamt 	if (!TCP_SACK_ENABLED(tp)) {
    521   1.9      yamt 		return 0;
    522   1.9      yamt 	}
    523   1.9      yamt 
    524  1.10      yamt 	numblks = (((tp->rcv_sack_flags & TCPSACK_HAVED) != 0) ? 1 : 0) +
    525  1.10      yamt 	    tp->t_segqlen;
    526  1.10      yamt 
    527  1.10      yamt 	if (numblks == 0) {
    528  1.10      yamt 		return 0;
    529  1.10      yamt 	}
    530  1.10      yamt 
    531  1.10      yamt 	if (numblks > TCP_SACK_MAX) {
    532  1.10      yamt 		numblks = TCP_SACK_MAX;
    533  1.10      yamt 	}
    534  1.10      yamt 
    535  1.10      yamt 	return numblks;
    536   1.9      yamt }
    537  1.22      yamt 
    538  1.22      yamt #if defined(DDB)
    539  1.22      yamt void sack_dump(const struct tcpcb *);
    540  1.22      yamt 
    541  1.22      yamt void
    542  1.22      yamt sack_dump(const struct tcpcb *tp)
    543  1.22      yamt {
    544  1.22      yamt 	const struct sackhole *cur;
    545  1.22      yamt 
    546  1.22      yamt 	printf("snd_una=%" PRIu32 ", snd_max=%" PRIu32 "\n",
    547  1.22      yamt 	    tp->snd_una, tp->snd_max);
    548  1.22      yamt 	printf("rcv_lastsack=%" PRIu32 ", snd_fack=%" PRIu32 "\n",
    549  1.22      yamt 	    tp->rcv_lastsack, tp->snd_fack);
    550  1.22      yamt 	printf("numholes=%d\n", tp->snd_numholes);
    551  1.22      yamt 	TAILQ_FOREACH(cur, &tp->snd_holes, sackhole_q) {
    552  1.22      yamt 		printf("\t%" PRIu32 "-%" PRIu32 ", rxmit=%" PRIu32 "\n",
    553  1.22      yamt 		    cur->start, cur->end, cur->rxmit);
    554  1.22      yamt 	}
    555  1.22      yamt }
    556  1.22      yamt #endif /* defined(DDB) */
    557