1 /*- 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)tcp_sack.c 8.12 (Berkeley) 5/24/95 30 * $FreeBSD$ 31 */ 32 33 /*- 34 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @@(#)COPYRIGHT 1.1 (NRL) 17 January 1995 62 * 63 * NRL grants permission for redistribution and use in source and binary 64 * forms, with or without modification, of the software and documentation 65 * created at NRL provided that the following conditions are met: 66 * 67 * 1. Redistributions of source code must retain the above copyright 68 * notice, this list of conditions and the following disclaimer. 69 * 2. Redistributions in binary form must reproduce the above copyright 70 * notice, this list of conditions and the following disclaimer in the 71 * documentation and/or other materials provided with the distribution. 72 * 3. All advertising materials mentioning features or use of this software 73 * must display the following acknowledgements: 74 * This product includes software developed by the University of 75 * California, Berkeley and its contributors. 76 * This product includes software developed at the Information 77 * Technology Division, US Naval Research Laboratory. 78 * 4. Neither the name of the NRL nor the names of its contributors 79 * may be used to endorse or promote products derived from this software 80 * without specific prior written permission. 81 * 82 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 83 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 84 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 85 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 86 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 87 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 88 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 89 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 90 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 91 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 92 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 93 * 94 * The views and conclusions contained in the software and documentation 95 * are those of the authors and should not be interpreted as representing 96 * official policies, either expressed or implied, of the US Naval 97 * Research Laboratory (NRL). 98 */ 99 #include "opt_inet.h" 100 #include "opt_inet6.h" 101 #include "opt_tcpdebug.h" 102 #include "opt_tcp_sack.h" 103 104 #include <sys/param.h> 105 #include <sys/systm.h> 106 #include <sys/kernel.h> 107 #include <sys/sysctl.h> 108 #include <sys/malloc.h> 109 #include <sys/mbuf.h> 110 #include <sys/proc.h> /* for proc0 declaration */ 111 #include <sys/protosw.h> 112 #include <sys/socket.h> 113 #include <sys/socketvar.h> 114 #include <sys/syslog.h> 115 #include <sys/systm.h> 116 117 #include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */ 118 119 #include <vm/uma.h> 120 121 #include <net/if.h> 122 #include <net/route.h> 123 124 #include <netinet/in.h> 125 #include <netinet/in_systm.h> 126 #include <netinet/ip.h> 127 #include <netinet/in_var.h> 128 #include <netinet/in_pcb.h> 129 #include <netinet/ip_var.h> 130 #include <netinet/ip6.h> 131 #include <netinet/icmp6.h> 132 #include <netinet6/nd6.h> 133 #include <netinet6/ip6_var.h> 134 #include <netinet6/in6_pcb.h> 135 #include <netinet/tcp.h> 136 #include <netinet/tcp_fsm.h> 137 #include <netinet/tcp_seq.h> 138 #include <netinet/tcp_timer.h> 139 #include <netinet/tcp_var.h> 140 #include <netinet6/tcp6_var.h> 141 #include <netinet/tcpip.h> 142 #ifdef TCPDEBUG 143 #include <netinet/tcp_debug.h> 144 #endif /* TCPDEBUG */ 145 146 #include <machine/in_cksum.h> 147 148 extern struct uma_zone *sack_hole_zone; 149 150 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, sack, CTLFLAG_RW, 0, "TCP SACK"); 151 int tcp_do_sack = 1; 152 SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, enable, CTLFLAG_RW, 153 &tcp_do_sack, 0, "Enable/Disable TCP SACK support"); 154 TUNABLE_INT("net.inet.tcp.sack.enable", &tcp_do_sack); 155 156 static int tcp_sack_maxholes = 128; 157 SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, maxholes, CTLFLAG_RW, 158 &tcp_sack_maxholes, 0, 159 "Maximum number of TCP SACK holes allowed per connection"); 160 161 static int tcp_sack_globalmaxholes = 65536; 162 SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, globalmaxholes, CTLFLAG_RW, 163 &tcp_sack_globalmaxholes, 0, 164 "Global maximum number of TCP SACK holes"); 165 166 static int tcp_sack_globalholes = 0; 167 SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, globalholes, CTLFLAG_RD, 168 &tcp_sack_globalholes, 0, 169 "Global number of TCP SACK holes currently allocated"); 170 171 /* 172 * This function is called upon receipt of new valid data (while not in header 173 * prediction mode), and it updates the ordered list of sacks. 174 */ 175 void 176 tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end) 177 { 178 /* 179 * First reported block MUST be the most recent one. Subsequent 180 * blocks SHOULD be in the order in which they arrived at the 181 * receiver. These two conditions make the implementation fully 182 * compliant with RFC 2018. 183 */ 184 struct sackblk head_blk, saved_blks[MAX_SACK_BLKS]; 185 int num_head, num_saved, i; 186 187 INP_LOCK_ASSERT(tp->t_inpcb); 188 189 /* Check arguments */ 190 KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end")); 191 192 /* SACK block for the received segment. */ 193 head_blk.start = rcv_start; 194 head_blk.end = rcv_end; 195 196 /* 197 * Merge updated SACK blocks into head_blk, and 198 * save unchanged SACK blocks into saved_blks[]. 199 * num_saved will have the number of the saved SACK blocks. 200 */ 201 num_saved = 0; 202 for (i = 0; i < tp->rcv_numsacks; i++) { 203 tcp_seq start = tp->sackblks[i].start; 204 tcp_seq end = tp->sackblks[i].end; 205 if (SEQ_GEQ(start, end) || SEQ_LEQ(start, tp->rcv_nxt)) { 206 /* 207 * Discard this SACK block. 208 */ 209 } else if (SEQ_LEQ(head_blk.start, end) && 210 SEQ_GEQ(head_blk.end, start)) { 211 /* 212 * Merge this SACK block into head_blk. 213 * This SACK block itself will be discarded. 214 */ 215 if (SEQ_GT(head_blk.start, start)) 216 head_blk.start = start; 217 if (SEQ_LT(head_blk.end, end)) 218 head_blk.end = end; 219 } else { 220 /* 221 * Save this SACK block. 222 */ 223 saved_blks[num_saved].start = start; 224 saved_blks[num_saved].end = end; 225 num_saved++; 226 } 227 } 228 229 /* 230 * Update SACK list in tp->sackblks[]. 231 */ 232 num_head = 0; 233 if (SEQ_GT(head_blk.start, tp->rcv_nxt)) { 234 /* 235 * The received data segment is an out-of-order segment. 236 * Put head_blk at the top of SACK list. 237 */ 238 tp->sackblks[0] = head_blk; 239 num_head = 1; 240 /* 241 * If the number of saved SACK blocks exceeds its limit, 242 * discard the last SACK block. 243 */ 244 if (num_saved >= MAX_SACK_BLKS) 245 num_saved--; 246 } 247 if (num_saved > 0) { 248 /* 249 * Copy the saved SACK blocks back. 250 */ 251 bcopy(saved_blks, &tp->sackblks[num_head], 252 sizeof(struct sackblk) * num_saved); 253 } 254 255 /* Save the number of SACK blocks. */ 256 tp->rcv_numsacks = num_head + num_saved; 257 } 258 259 /* 260 * Delete all receiver-side SACK information. 261 */ 262 void 263 tcp_clean_sackreport(tp) 264 struct tcpcb *tp; 265 { 266 int i; 267 268 INP_LOCK_ASSERT(tp->t_inpcb); 269 tp->rcv_numsacks = 0; 270 for (i = 0; i < MAX_SACK_BLKS; i++) 271 tp->sackblks[i].start = tp->sackblks[i].end=0; 272 } 273 274 /* 275 * Allocate struct sackhole. 276 */ 277 static struct sackhole * 278 tcp_sackhole_alloc(struct tcpcb *tp, tcp_seq start, tcp_seq end) 279 { 280 struct sackhole *hole; 281 282 if (tp->snd_numholes >= tcp_sack_maxholes || 283 tcp_sack_globalholes >= tcp_sack_globalmaxholes) { 284 tcpstat.tcps_sack_sboverflow++; 285 return NULL; 286 } 287 288 hole = (struct sackhole *)uma_zalloc(sack_hole_zone, M_NOWAIT); 289 if (hole == NULL) 290 return NULL; 291 292 hole->start = start; 293 hole->end = end; 294 hole->rxmit = start; 295 296 tp->snd_numholes++; 297 tcp_sack_globalholes++; 298 299 return hole; 300 } 301 302 /* 303 * Free struct sackhole. 304 */ 305 static void 306 tcp_sackhole_free(struct tcpcb *tp, struct sackhole *hole) 307 { 308 uma_zfree(sack_hole_zone, hole); 309 310 tp->snd_numholes--; 311 tcp_sack_globalholes--; 312 313 KASSERT(tp->snd_numholes >= 0, ("tp->snd_numholes >= 0")); 314 KASSERT(tcp_sack_globalholes >= 0, ("tcp_sack_globalholes >= 0")); 315 } 316 317 /* 318 * Insert new SACK hole into scoreboard. 319 */ 320 static struct sackhole * 321 tcp_sackhole_insert(struct tcpcb *tp, tcp_seq start, tcp_seq end, 322 struct sackhole *after) 323 { 324 struct sackhole *hole; 325 326 /* Allocate a new SACK hole. */ 327 hole = tcp_sackhole_alloc(tp, start, end); 328 if (hole == NULL) 329 return NULL; 330 331 /* Insert the new SACK hole into scoreboard */ 332 if (after != NULL) 333 TAILQ_INSERT_AFTER(&tp->snd_holes, after, hole, scblink); 334 else 335 TAILQ_INSERT_TAIL(&tp->snd_holes, hole, scblink); 336 337 /* Update SACK hint. */ 338 if (tp->sackhint.nexthole == NULL) 339 tp->sackhint.nexthole = hole; 340 341 return hole; 342 } 343 344 /* 345 * Remove SACK hole from scoreboard. 346 */ 347 static void 348 tcp_sackhole_remove(struct tcpcb *tp, struct sackhole *hole) 349 { 350 /* Update SACK hint. */ 351 if (tp->sackhint.nexthole == hole) 352 tp->sackhint.nexthole = TAILQ_NEXT(hole, scblink); 353 354 /* Remove this SACK hole. */ 355 TAILQ_REMOVE(&tp->snd_holes, hole, scblink); 356 357 /* Free this SACK hole. */ 358 tcp_sackhole_free(tp, hole); 359 } 360 361 /* 362 * Process cumulative ACK and the TCP SACK option to update the scoreboard. 363 * tp->snd_holes is an ordered list of holes (oldest to newest, in terms of 364 * the sequence space). 365 */ 366 void 367 tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) 368 { 369 struct sackhole *cur, *temp; 370 struct sackblk sack, sack_blocks[TCP_MAX_SACK + 1], *sblkp; 371 int i, j, num_sack_blks; 372 373 INP_LOCK_ASSERT(tp->t_inpcb); 374 375 num_sack_blks = 0; 376 /* 377 * If SND.UNA will be advanced by SEG.ACK, and if SACK holes exist, 378 * treat [SND.UNA, SEG.ACK) as if it is a SACK block. 379 */ 380 if (SEQ_LT(tp->snd_una, th_ack) && !TAILQ_EMPTY(&tp->snd_holes)) { 381 sack_blocks[num_sack_blks].start = tp->snd_una; 382 sack_blocks[num_sack_blks++].end = th_ack; 383 } 384 /* 385 * Append received valid SACK blocks to sack_blocks[], but only 386 * if we received new blocks from the other side. 387 */ 388 if (to->to_flags & TOF_SACK) { 389 for (i = 0; i < to->to_nsacks; i++) { 390 bcopy((to->to_sacks + i * TCPOLEN_SACK), 391 &sack, sizeof(sack)); 392 sack.start = ntohl(sack.start); 393 sack.end = ntohl(sack.end); 394 if (SEQ_GT(sack.end, sack.start) && 395 SEQ_GT(sack.start, tp->snd_una) && 396 SEQ_GT(sack.start, th_ack) && 397 SEQ_LT(sack.start, tp->snd_max) && 398 SEQ_GT(sack.end, tp->snd_una) && 399 SEQ_LEQ(sack.end, tp->snd_max)) 400 sack_blocks[num_sack_blks++] = sack; 401 } 402 } 403 /* 404 * Return if SND.UNA is not advanced and no valid SACK block 405 * is received. 406 */ 407 if (num_sack_blks == 0) 408 return; 409 410 /* 411 * Sort the SACK blocks so we can update the scoreboard 412 * with just one pass. The overhead of sorting upto 4+1 elements 413 * is less than making upto 4+1 passes over the scoreboard. 414 */ 415 for (i = 0; i < num_sack_blks; i++) { 416 for (j = i + 1; j < num_sack_blks; j++) { 417 if (SEQ_GT(sack_blocks[i].end, sack_blocks[j].end)) { 418 sack = sack_blocks[i]; 419 sack_blocks[i] = sack_blocks[j]; 420 sack_blocks[j] = sack; 421 } 422 } 423 } 424 if (TAILQ_EMPTY(&tp->snd_holes)) 425 /* 426 * Empty scoreboard. Need to initialize snd_fack (it may be 427 * uninitialized or have a bogus value). Scoreboard holes 428 * (from the sack blocks received) are created later below (in 429 * the logic that adds holes to the tail of the scoreboard). 430 */ 431 tp->snd_fack = SEQ_MAX(tp->snd_una, th_ack); 432 /* 433 * In the while-loop below, incoming SACK blocks (sack_blocks[]) 434 * and SACK holes (snd_holes) are traversed from their tails with 435 * just one pass in order to reduce the number of compares especially 436 * when the bandwidth-delay product is large. 437 * Note: Typically, in the first RTT of SACK recovery, the highest 438 * three or four SACK blocks with the same ack number are received. 439 * In the second RTT, if retransmitted data segments are not lost, 440 * the highest three or four SACK blocks with ack number advancing 441 * are received. 442 */ 443 sblkp = &sack_blocks[num_sack_blks - 1]; /* Last SACK block */ 444 if (SEQ_LT(tp->snd_fack, sblkp->start)) { 445 /* 446 * The highest SACK block is beyond fack. 447 * Append new SACK hole at the tail. 448 * If the second or later highest SACK blocks are also 449 * beyond the current fack, they will be inserted by 450 * way of hole splitting in the while-loop below. 451 */ 452 temp = tcp_sackhole_insert(tp, tp->snd_fack,sblkp->start,NULL); 453 if (temp != NULL) { 454 tp->snd_fack = sblkp->end; 455 /* Go to the previous sack block. */ 456 sblkp--; 457 } else { 458 /* 459 * We failed to add a new hole based on the current 460 * sack block. Skip over all the sack blocks that 461 * fall completely to the right of snd_fack and proceed 462 * to trim the scoreboard based on the remaining sack 463 * blocks. This also trims the scoreboard for th_ack 464 * (which is sack_blocks[0]). 465 */ 466 while (sblkp >= sack_blocks && 467 SEQ_LT(tp->snd_fack, sblkp->start)) 468 sblkp--; 469 if (sblkp >= sack_blocks && 470 SEQ_LT(tp->snd_fack, sblkp->end)) 471 tp->snd_fack = sblkp->end; 472 } 473 } else if (SEQ_LT(tp->snd_fack, sblkp->end)) 474 /* fack is advanced. */ 475 tp->snd_fack = sblkp->end; 476 /* We must have at least one SACK hole in scoreboard */ 477 KASSERT(!TAILQ_EMPTY(&tp->snd_holes), ("SACK scoreboard must not be empty")); 478 cur = TAILQ_LAST(&tp->snd_holes, sackhole_head); /* Last SACK hole */ 479 /* 480 * Since the incoming sack blocks are sorted, we can process them 481 * making one sweep of the scoreboard. 482 */ 483 while (sblkp >= sack_blocks && cur != NULL) { 484 if (SEQ_GEQ(sblkp->start, cur->end)) { 485 /* 486 * SACKs data beyond the current hole. 487 * Go to the previous sack block. 488 */ 489 sblkp--; 490 continue; 491 } 492 if (SEQ_LEQ(sblkp->end, cur->start)) { 493 /* 494 * SACKs data before the current hole. 495 * Go to the previous hole. 496 */ 497 cur = TAILQ_PREV(cur, sackhole_head, scblink); 498 continue; 499 } 500 tp->sackhint.sack_bytes_rexmit -= (cur->rxmit - cur->start); 501 KASSERT(tp->sackhint.sack_bytes_rexmit >= 0, 502 ("sackhint bytes rtx >= 0")); 503 if (SEQ_LEQ(sblkp->start, cur->start)) { 504 /* Data acks at least the beginning of hole */ 505 if (SEQ_GEQ(sblkp->end, cur->end)) { 506 /* Acks entire hole, so delete hole */ 507 temp = cur; 508 cur = TAILQ_PREV(cur, sackhole_head, scblink); 509 tcp_sackhole_remove(tp, temp); 510 /* 511 * The sack block may ack all or part of the next 512 * hole too, so continue onto the next hole. 513 */ 514 continue; 515 } else { 516 /* Move start of hole forward */ 517 cur->start = sblkp->end; 518 cur->rxmit = SEQ_MAX(cur->rxmit, cur->start); 519 } 520 } else { 521 /* Data acks at least the end of hole */ 522 if (SEQ_GEQ(sblkp->end, cur->end)) { 523 /* Move end of hole backward */ 524 cur->end = sblkp->start; 525 cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); 526 } else { 527 /* 528 * ACKs some data in middle of a hole; need to 529 * split current hole 530 */ 531 temp = tcp_sackhole_insert(tp, sblkp->end, 532 cur->end, cur); 533 if (temp != NULL) { 534 if (SEQ_GT(cur->rxmit, temp->rxmit)) { 535 temp->rxmit = cur->rxmit; 536 tp->sackhint.sack_bytes_rexmit 537 += (temp->rxmit 538 - temp->start); 539 } 540 cur->end = sblkp->start; 541 cur->rxmit = SEQ_MIN(cur->rxmit, 542 cur->end); 543 } 544 } 545 } 546 tp->sackhint.sack_bytes_rexmit += (cur->rxmit - cur->start); 547 /* 548 * Testing sblkp->start against cur->start tells us whether 549 * we're done with the sack block or the sack hole. 550 * Accordingly, we advance one or the other. 551 */ 552 if (SEQ_LEQ(sblkp->start, cur->start)) 553 cur = TAILQ_PREV(cur, sackhole_head, scblink); 554 else 555 sblkp--; 556 } 557 } 558 559 /* 560 * Free all SACK holes to clear the scoreboard. 561 */ 562 void 563 tcp_free_sackholes(struct tcpcb *tp) 564 { 565 struct sackhole *q; 566 567 INP_LOCK_ASSERT(tp->t_inpcb); 568 while ((q = TAILQ_FIRST(&tp->snd_holes)) != NULL) 569 tcp_sackhole_remove(tp, q); 570 tp->sackhint.sack_bytes_rexmit = 0; 571 572 KASSERT(tp->snd_numholes == 0, ("tp->snd_numholes == 0")); 573 KASSERT(tp->sackhint.nexthole == NULL, 574 ("tp->sackhint.nexthole == NULL")); 575 } 576 577 /* 578 * Partial ack handling within a sack recovery episode. 579 * Keeping this very simple for now. When a partial ack 580 * is received, force snd_cwnd to a value that will allow 581 * the sender to transmit no more than 2 segments. 582 * If necessary, a better scheme can be adopted at a 583 * later point, but for now, the goal is to prevent the 584 * sender from bursting a large amount of data in the midst 585 * of sack recovery. 586 */ 587 void 588 tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th) 589 { 590 int num_segs = 1; 591 592 INP_LOCK_ASSERT(tp->t_inpcb); 593 callout_stop(tp->tt_rexmt); 594 tp->t_rtttime = 0; 595 /* send one or 2 segments based on how much new data was acked */ 596 if (((th->th_ack - tp->snd_una) / tp->t_maxseg) > 2) 597 num_segs = 2; 598 tp->snd_cwnd = (tp->sackhint.sack_bytes_rexmit + 599 (tp->snd_nxt - tp->sack_newdata) + 600 num_segs * tp->t_maxseg); 601 if (tp->snd_cwnd > tp->snd_ssthresh) 602 tp->snd_cwnd = tp->snd_ssthresh; 603 tp->t_flags |= TF_ACKNOW; 604 (void) tcp_output(tp); 605 } 606 607 #if 0 608 /* 609 * Debug version of tcp_sack_output() that walks the scoreboard. Used for 610 * now to sanity check the hint. 611 */ 612 static struct sackhole * 613 tcp_sack_output_debug(struct tcpcb *tp, int *sack_bytes_rexmt) 614 { 615 struct sackhole *p; 616 617 INP_LOCK_ASSERT(tp->t_inpcb); 618 *sack_bytes_rexmt = 0; 619 TAILQ_FOREACH(p, &tp->snd_holes, scblink) { 620 if (SEQ_LT(p->rxmit, p->end)) { 621 if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */ 622 continue; 623 } 624 *sack_bytes_rexmt += (p->rxmit - p->start); 625 break; 626 } 627 *sack_bytes_rexmt += (p->rxmit - p->start); 628 } 629 return (p); 630 } 631 #endif 632 633 /* 634 * Returns the next hole to retransmit and the number of retransmitted bytes 635 * from the scoreboard. We store both the next hole and the number of 636 * retransmitted bytes as hints (and recompute these on the fly upon SACK/ACK 637 * reception). This avoids scoreboard traversals completely. 638 * 639 * The loop here will traverse *at most* one link. Here's the argument. 640 * For the loop to traverse more than 1 link before finding the next hole to 641 * retransmit, we would need to have at least 1 node following the current hint 642 * with (rxmit == end). But, for all holes following the current hint, 643 * (start == rxmit), since we have not yet retransmitted from them. Therefore, 644 * in order to traverse more 1 link in the loop below, we need to have at least 645 * one node following the current hint with (start == rxmit == end). 646 * But that can't happen, (start == end) means that all the data in that hole 647 * has been sacked, in which case, the hole would have been removed from the 648 * scoreboard. 649 */ 650 struct sackhole * 651 tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt) 652 { 653 struct sackhole *hole = NULL; 654 655 INP_LOCK_ASSERT(tp->t_inpcb); 656 *sack_bytes_rexmt = tp->sackhint.sack_bytes_rexmit; 657 hole = tp->sackhint.nexthole; 658 if (hole == NULL || SEQ_LT(hole->rxmit, hole->end)) 659 goto out; 660 while ((hole = TAILQ_NEXT(hole, scblink)) != NULL) { 661 if (SEQ_LT(hole->rxmit, hole->end)) { 662 tp->sackhint.nexthole = hole; 663 break; 664 } 665 } 666 out: 667 return (hole); 668 } 669 670 /* 671 * After a timeout, the SACK list may be rebuilt. This SACK information 672 * should be used to avoid retransmitting SACKed data. This function 673 * traverses the SACK list to see if snd_nxt should be moved forward. 674 */ 675 void 676 tcp_sack_adjust(struct tcpcb *tp) 677 { 678 struct sackhole *p, *cur = TAILQ_FIRST(&tp->snd_holes); 679 680 INP_LOCK_ASSERT(tp->t_inpcb); 681 if (cur == NULL) 682 return; /* No holes */ 683 if (SEQ_GEQ(tp->snd_nxt, tp->snd_fack)) 684 return; /* We're already beyond any SACKed blocks */ 685 /* 686 * Two cases for which we want to advance snd_nxt: 687 * i) snd_nxt lies between end of one hole and beginning of another 688 * ii) snd_nxt lies between end of last hole and snd_fack 689 */ 690 while ((p = TAILQ_NEXT(cur, scblink)) != NULL) { 691 if (SEQ_LT(tp->snd_nxt, cur->end)) 692 return; 693 if (SEQ_GEQ(tp->snd_nxt, p->start)) 694 cur = p; 695 else { 696 tp->snd_nxt = p->start; 697 return; 698 } 699 } 700 if (SEQ_LT(tp->snd_nxt, cur->end)) 701 return; 702 tp->snd_nxt = tp->snd_fack; 703 return; 704 } 705