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_ipsec.h" 102 #include "opt_tcpdebug.h" 103 #include "opt_tcp_input.h" 104 #include "opt_tcp_sack.h" 105 106 #include <sys/param.h> 107 #include <sys/systm.h> 108 #include <sys/kernel.h> 109 #include <sys/sysctl.h> 110 #include <sys/malloc.h> 111 #include <sys/mbuf.h> 112 #include <sys/proc.h> /* for proc0 declaration */ 113 #include <sys/protosw.h> 114 #include <sys/socket.h> 115 #include <sys/socketvar.h> 116 #include <sys/syslog.h> 117 #include <sys/systm.h> 118 119 #include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */ 120 121 #include <vm/uma.h> 122 123 #include <net/if.h> 124 #include <net/route.h> 125 126 #include <netinet/in.h> 127 #include <netinet/in_systm.h> 128 #include <netinet/ip.h> 129 #include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */ 130 #include <netinet/in_var.h> 131 #include <netinet/icmp_var.h> /* for ICMP_BANDLIM */ 132 #include <netinet/in_pcb.h> 133 #include <netinet/ip_var.h> 134 #include <netinet/ip6.h> 135 #include <netinet/icmp6.h> 136 #include <netinet6/nd6.h> 137 #include <netinet6/ip6_var.h> 138 #include <netinet6/in6_pcb.h> 139 #include <netinet/tcp.h> 140 #include <netinet/tcp_fsm.h> 141 #include <netinet/tcp_seq.h> 142 #include <netinet/tcp_timer.h> 143 #include <netinet/tcp_var.h> 144 #include <netinet6/tcp6_var.h> 145 #include <netinet/tcpip.h> 146 #ifdef TCPDEBUG 147 #include <netinet/tcp_debug.h> 148 149 u_char tcp_saveipgen[40]; /* the size must be of max ip header, now IPv6 */ 150 struct tcphdr tcp_savetcp; 151 #endif /* TCPDEBUG */ 152 153 #ifdef FAST_IPSEC 154 #include <netipsec/ipsec.h> 155 #include <netipsec/ipsec6.h> 156 #endif 157 158 #ifdef IPSEC 159 #include <netinet6/ipsec.h> 160 #include <netinet6/ipsec6.h> 161 #include <netkey/key.h> 162 #endif /*IPSEC*/ 163 #include <machine/in_cksum.h> 164 165 extern struct uma_zone *sack_hole_zone; 166 167 /* 168 * This function is called upon receipt of new valid data (while not in header 169 * prediction mode), and it updates the ordered list of sacks. 170 */ 171 void 172 tcp_update_sack_list(tp) 173 struct tcpcb *tp; 174 { 175 /* 176 * First reported block MUST be the most recent one. Subsequent 177 * blocks SHOULD be in the order in which they arrived at the 178 * receiver. These two conditions make the implementation fully 179 * compliant with RFC 2018. 180 */ 181 int i, j = 0, count = 0, lastpos = -1; 182 struct sackblk sack, firstsack, temp[MAX_SACK_BLKS]; 183 184 INP_LOCK_ASSERT(tp->t_inpcb); 185 /* First clean up current list of sacks */ 186 for (i = 0; i < tp->rcv_numsacks; i++) { 187 sack = tp->sackblks[i]; 188 if (sack.start == 0 && sack.end == 0) { 189 count++; /* count = number of blocks to be discarded */ 190 continue; 191 } 192 if (SEQ_LEQ(sack.end, tp->rcv_nxt)) { 193 tp->sackblks[i].start = tp->sackblks[i].end = 0; 194 count++; 195 } else { 196 temp[j].start = tp->sackblks[i].start; 197 temp[j++].end = tp->sackblks[i].end; 198 } 199 } 200 tp->rcv_numsacks -= count; 201 if (tp->rcv_numsacks == 0) { /* no sack blocks currently (fast path) */ 202 tcp_clean_sackreport(tp); 203 if (SEQ_LT(tp->rcv_nxt, tp->rcv_laststart)) { 204 /* ==> need first sack block */ 205 tp->sackblks[0].start = tp->rcv_laststart; 206 tp->sackblks[0].end = tp->rcv_lastend; 207 tp->rcv_numsacks = 1; 208 } 209 return; 210 } 211 /* Otherwise, sack blocks are already present. */ 212 for (i = 0; i < tp->rcv_numsacks; i++) 213 tp->sackblks[i] = temp[i]; /* first copy back sack list */ 214 if (SEQ_GEQ(tp->rcv_nxt, tp->rcv_lastend)) 215 return; /* sack list remains unchanged */ 216 /* 217 * From here, segment just received should be (part of) the 1st sack. 218 * Go through list, possibly coalescing sack block entries. 219 */ 220 firstsack.start = tp->rcv_laststart; 221 firstsack.end = tp->rcv_lastend; 222 for (i = 0; i < tp->rcv_numsacks; i++) { 223 sack = tp->sackblks[i]; 224 if (SEQ_LT(sack.end, firstsack.start) || 225 SEQ_GT(sack.start, firstsack.end)) 226 continue; /* no overlap */ 227 if (sack.start == firstsack.start && sack.end == firstsack.end){ 228 /* 229 * identical block; delete it here since we will 230 * move it to the front of the list. 231 */ 232 tp->sackblks[i].start = tp->sackblks[i].end = 0; 233 lastpos = i; /* last posn with a zero entry */ 234 continue; 235 } 236 if (SEQ_LEQ(sack.start, firstsack.start)) 237 firstsack.start = sack.start; /* merge blocks */ 238 if (SEQ_GEQ(sack.end, firstsack.end)) 239 firstsack.end = sack.end; /* merge blocks */ 240 tp->sackblks[i].start = tp->sackblks[i].end = 0; 241 lastpos = i; /* last posn with a zero entry */ 242 } 243 if (lastpos != -1) { /* at least one merge */ 244 for (i = 0, j = 1; i < tp->rcv_numsacks; i++) { 245 sack = tp->sackblks[i]; 246 if (sack.start == 0 && sack.end == 0) 247 continue; 248 temp[j++] = sack; 249 } 250 tp->rcv_numsacks = j; /* including first blk (added later) */ 251 for (i = 1; i < tp->rcv_numsacks; i++) /* now copy back */ 252 tp->sackblks[i] = temp[i]; 253 } else { /* no merges -- shift sacks by 1 */ 254 if (tp->rcv_numsacks < MAX_SACK_BLKS) 255 tp->rcv_numsacks++; 256 for (i = tp->rcv_numsacks-1; i > 0; i--) 257 tp->sackblks[i] = tp->sackblks[i-1]; 258 } 259 tp->sackblks[0] = firstsack; 260 return; 261 } 262 263 /* 264 * Delete all receiver-side SACK information. 265 */ 266 void 267 tcp_clean_sackreport(tp) 268 struct tcpcb *tp; 269 { 270 int i; 271 272 INP_LOCK_ASSERT(tp->t_inpcb); 273 tp->rcv_numsacks = 0; 274 for (i = 0; i < MAX_SACK_BLKS; i++) 275 tp->sackblks[i].start = tp->sackblks[i].end=0; 276 } 277 278 /* 279 * Process the TCP SACK option. Returns 1 if tcp_dooptions() should continue, 280 * and 0 otherwise, if the option was fine. tp->snd_holes is an ordered list 281 * of holes (oldest to newest, in terms of the sequence space). 282 */ 283 int 284 tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen) 285 { 286 int tmp_olen; 287 u_char *tmp_cp; 288 struct sackhole *cur, *p, *temp; 289 290 INP_LOCK_ASSERT(tp->t_inpcb); 291 if (!tp->sack_enable) 292 return (1); 293 294 /* Note: TCPOLEN_SACK must be 2*sizeof(tcp_seq) */ 295 if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0) 296 return (1); 297 tmp_cp = cp + 2; 298 tmp_olen = optlen - 2; 299 tcpstat.tcps_sack_rcv_blocks++; 300 if (tp->snd_numholes < 0) 301 tp->snd_numholes = 0; 302 if (tp->t_maxseg == 0) 303 panic("tcp_sack_option"); /* Should never happen */ 304 while (tmp_olen > 0) { 305 struct sackblk sack; 306 307 bcopy(tmp_cp, (char *) &(sack.start), sizeof(tcp_seq)); 308 sack.start = ntohl(sack.start); 309 bcopy(tmp_cp + sizeof(tcp_seq), 310 (char *) &(sack.end), sizeof(tcp_seq)); 311 sack.end = ntohl(sack.end); 312 tmp_olen -= TCPOLEN_SACK; 313 tmp_cp += TCPOLEN_SACK; 314 if (SEQ_LEQ(sack.end, sack.start)) 315 continue; /* bad SACK fields */ 316 if (SEQ_LEQ(sack.end, tp->snd_una)) 317 continue; /* old block */ 318 if (SEQ_GT(th->th_ack, tp->snd_una)) { 319 if (SEQ_LT(sack.start, th->th_ack)) 320 continue; 321 } 322 if (SEQ_GT(sack.end, tp->snd_max)) 323 continue; 324 if (tp->snd_holes == NULL) { /* first hole */ 325 tp->snd_holes = (struct sackhole *) 326 uma_zalloc(sack_hole_zone,M_NOWAIT); 327 if (tp->snd_holes == NULL) { 328 /* ENOBUFS, so ignore SACKed block for now*/ 329 continue; 330 } 331 cur = tp->snd_holes; 332 cur->start = th->th_ack; 333 cur->end = sack.start; 334 cur->rxmit = cur->start; 335 cur->next = NULL; 336 tp->snd_numholes = 1; 337 tp->rcv_lastsack = sack.end; 338 continue; /* with next sack block */ 339 } 340 /* Go thru list of holes: p = previous, cur = current */ 341 p = cur = tp->snd_holes; 342 while (cur) { 343 if (SEQ_LEQ(sack.end, cur->start)) 344 /* SACKs data before the current hole */ 345 break; /* no use going through more holes */ 346 if (SEQ_GEQ(sack.start, cur->end)) { 347 /* SACKs data beyond the current hole */ 348 p = cur; 349 cur = cur->next; 350 continue; 351 } 352 if (SEQ_LEQ(sack.start, cur->start)) { 353 /* Data acks at least the beginning of hole */ 354 if (SEQ_GEQ(sack.end, cur->end)) { 355 /* Acks entire hole, so delete hole */ 356 if (p != cur) { 357 p->next = cur->next; 358 uma_zfree(sack_hole_zone, cur); 359 cur = p->next; 360 } else { 361 cur = cur->next; 362 uma_zfree(sack_hole_zone, p); 363 p = cur; 364 tp->snd_holes = p; 365 } 366 tp->snd_numholes--; 367 continue; 368 } 369 /* otherwise, move start of hole forward */ 370 cur->start = sack.end; 371 cur->rxmit = SEQ_MAX(cur->rxmit, cur->start); 372 p = cur; 373 cur = cur->next; 374 continue; 375 } 376 /* move end of hole backward */ 377 if (SEQ_GEQ(sack.end, cur->end)) { 378 cur->end = sack.start; 379 cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); 380 p = cur; 381 cur = cur->next; 382 continue; 383 } 384 if (SEQ_LT(cur->start, sack.start) && 385 SEQ_GT(cur->end, sack.end)) { 386 /* 387 * ACKs some data in middle of a hole; need to 388 * split current hole 389 */ 390 temp = (struct sackhole *) 391 uma_zalloc(sack_hole_zone,M_NOWAIT); 392 if (temp == NULL) 393 continue; /* ENOBUFS */ 394 temp->next = cur->next; 395 temp->start = sack.end; 396 temp->end = cur->end; 397 temp->rxmit = SEQ_MAX(cur->rxmit, temp->start); 398 cur->end = sack.start; 399 cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); 400 cur->next = temp; 401 p = temp; 402 cur = p->next; 403 tp->snd_numholes++; 404 } 405 } 406 /* At this point, p points to the last hole on the list */ 407 if (SEQ_LT(tp->rcv_lastsack, sack.start)) { 408 /* 409 * Need to append new hole at end. 410 * Last hole is p (and it's not NULL). 411 */ 412 temp = (struct sackhole *) 413 uma_zalloc(sack_hole_zone,M_NOWAIT); 414 if (temp == NULL) 415 continue; /* ENOBUFS */ 416 temp->start = tp->rcv_lastsack; 417 temp->end = sack.start; 418 temp->rxmit = temp->start; 419 temp->next = 0; 420 p->next = temp; 421 tp->rcv_lastsack = sack.end; 422 tp->snd_numholes++; 423 } 424 } 425 return (0); 426 } 427 428 /* 429 * Delete stale (i.e, cumulatively ack'd) holes. Hole is deleted only if 430 * it is completely acked; otherwise, tcp_sack_option(), called from 431 * tcp_dooptions(), will fix up the hole. 432 */ 433 void 434 tcp_del_sackholes(tp, th) 435 struct tcpcb *tp; 436 struct tcphdr *th; 437 { 438 INP_LOCK_ASSERT(tp->t_inpcb); 439 if (tp->sack_enable && tp->t_state != TCPS_LISTEN) { 440 /* max because this could be an older ack just arrived */ 441 tcp_seq lastack = SEQ_GT(th->th_ack, tp->snd_una) ? 442 th->th_ack : tp->snd_una; 443 struct sackhole *cur = tp->snd_holes; 444 struct sackhole *prev; 445 while (cur) 446 if (SEQ_LEQ(cur->end, lastack)) { 447 prev = cur; 448 cur = cur->next; 449 uma_zfree(sack_hole_zone, prev); 450 tp->snd_numholes--; 451 } else if (SEQ_LT(cur->start, lastack)) { 452 cur->start = lastack; 453 if (SEQ_LT(cur->rxmit, cur->start)) 454 cur->rxmit = cur->start; 455 break; 456 } else 457 break; 458 tp->snd_holes = cur; 459 } 460 } 461 462 void 463 tcp_free_sackholes(struct tcpcb *tp) 464 { 465 struct sackhole *p, *q; 466 467 INP_LOCK_ASSERT(tp->t_inpcb); 468 q = tp->snd_holes; 469 while (q != NULL) { 470 p = q; 471 q = q->next; 472 uma_zfree(sack_hole_zone, p); 473 } 474 tp->snd_holes = 0; 475 } 476 477 /* 478 * Checks for partial ack. If partial ack arrives, turn off retransmission 479 * timer, deflate the window, do not clear tp->t_dupacks, and return 1. 480 * If the ack advances at least to tp->snd_recover, return 0. 481 */ 482 void 483 tcp_sack_partialack(tp, th) 484 struct tcpcb *tp; 485 struct tcphdr *th; 486 { 487 INP_LOCK_ASSERT(tp->t_inpcb); 488 u_long ocwnd = tp->snd_cwnd; 489 490 callout_stop(tp->tt_rexmt); 491 tp->t_rtttime = 0; 492 /* 493 * Set snd_cwnd to one segment beyond acknowledged offset 494 * (tp->snd_una has not yet been updated when this function is called.) 495 */ 496 /* 497 * Should really be 498 * min(tp->snd_cwnd, tp->t_maxseg + (th->th_ack - tp->snd_una)) 499 */ 500 tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una); 501 tp->t_flags |= TF_ACKNOW; 502 (void) tcp_output(tp); 503 tp->snd_cwnd = ocwnd; 504 /* 505 * Partial window deflation. Relies on fact that tp->snd_una 506 * not updated yet. 507 */ 508 tp->snd_cwnd -= (th->th_ack - tp->snd_una - tp->t_maxseg); 509 } 510 511 #ifdef TCP_SACK_DEBUG 512 void 513 tcp_print_holes(struct tcpcb *tp) 514 { 515 struct sackhole *p = tp->snd_holes; 516 if (p == 0) 517 return; 518 printf("Hole report: start--end dups rxmit\n"); 519 while (p) { 520 printf("%x--%x r %x\n", p->start, p->end, p->rxmit); 521 p = p->next; 522 } 523 printf("\n"); 524 } 525 #endif /* TCP_SACK_DEBUG */ 526 527 /* 528 * Returns pointer to a sackhole if there are any pending retransmissions; 529 * NULL otherwise. 530 */ 531 struct sackhole * 532 tcp_sack_output(struct tcpcb *tp) 533 { 534 struct sackhole *p; 535 536 INP_LOCK_ASSERT(tp->t_inpcb); 537 if (!tp->sack_enable) 538 return (NULL); 539 p = tp->snd_holes; 540 while (p) { 541 if (SEQ_LT(p->rxmit, p->end)) { 542 if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */ 543 p = p->next; 544 continue; 545 } 546 #ifdef TCP_SACK_DEBUG 547 if (p) 548 tcp_print_holes(tp); 549 #endif 550 return (p); 551 } 552 p = p->next; 553 } 554 return (NULL); 555 } 556 557 /* 558 * After a timeout, the SACK list may be rebuilt. This SACK information 559 * should be used to avoid retransmitting SACKed data. This function 560 * traverses the SACK list to see if snd_nxt should be moved forward. 561 */ 562 void 563 tcp_sack_adjust(struct tcpcb *tp) 564 { 565 INP_LOCK_ASSERT(tp->t_inpcb); 566 struct sackhole *cur = tp->snd_holes; 567 if (cur == NULL) 568 return; /* No holes */ 569 if (SEQ_GEQ(tp->snd_nxt, tp->rcv_lastsack)) 570 return; /* We're already beyond any SACKed blocks */ 571 /* 572 * Two cases for which we want to advance snd_nxt: 573 * i) snd_nxt lies between end of one hole and beginning of another 574 * ii) snd_nxt lies between end of last hole and rcv_lastsack 575 */ 576 while (cur->next) { 577 if (SEQ_LT(tp->snd_nxt, cur->end)) 578 return; 579 if (SEQ_GEQ(tp->snd_nxt, cur->next->start)) 580 cur = cur->next; 581 else { 582 tp->snd_nxt = cur->next->start; 583 return; 584 } 585 } 586 if (SEQ_LT(tp->snd_nxt, cur->end)) 587 return; 588 tp->snd_nxt = tp->rcv_lastsack; 589 return; 590 } 591 592