Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -449,6 +449,8 @@ case CC_NDUPACK: if (!IN_FASTRECOVERY(tp->t_flags)) { tp->snd_recover = tp->snd_max; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + tp->snd_recover--; if (tp->t_flags2 & TF2_ECN_PERMIT) tp->t_flags2 |= TF2_ECN_SND_CWR; } @@ -463,6 +465,8 @@ EXIT_CONGRECOVERY(tp->t_flags); TCPSTAT_INC(tcps_ecn_rcwnd); tp->snd_recover = tp->snd_max + 1; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + tp->snd_recover -= 2; if (tp->t_flags2 & TF2_ECN_PERMIT) tp->t_flags2 |= TF2_ECN_SND_CWR; } @@ -485,6 +489,8 @@ if (tp->t_flags & TF_WASCRECOVERY) ENTER_CONGRECOVERY(tp->t_flags); tp->snd_nxt = tp->snd_max; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + tp->snd_nxt--; tp->t_flags &= ~TF_PREVVALID; tp->t_badrxtwin = 0; break; @@ -4014,7 +4020,12 @@ int tcp_compute_pipe(struct tcpcb *tp) { - return (tp->snd_max - tp->snd_una + + int highdata; + + highdata = tp->snd_max; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + highdata--; + return (highdata - tp->snd_una + tp->sackhint.sack_bytes_rexmit - tp->sackhint.sacked_bytes); } Index: sys/netinet/tcp_sack.c =================================================================== --- sys/netinet/tcp_sack.c +++ sys/netinet/tcp_sack.c @@ -543,6 +543,7 @@ struct sackblk sack, sack_blocks[TCP_MAX_SACK + 1], *sblkp; int i, j, num_sack_blks, sack_changed; int delivered_data, left_edge_delta; + int highdata; INP_WLOCK_ASSERT(tp->t_inpcb); @@ -565,6 +566,9 @@ * received new blocks from the other side. */ if (to->to_flags & TOF_SACK) { + highdata = tp->snd_max; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + highdata--; for (i = 0; i < to->to_nsacks; i++) { bcopy((to->to_sacks + i * TCPOLEN_SACK), &sack, sizeof(sack)); @@ -573,9 +577,9 @@ if (SEQ_GT(sack.end, sack.start) && SEQ_GT(sack.start, tp->snd_una) && SEQ_GT(sack.start, th_ack) && - SEQ_LT(sack.start, tp->snd_max) && + SEQ_LT(sack.start, highdata) && SEQ_GT(sack.end, tp->snd_una) && - SEQ_LEQ(sack.end, tp->snd_max)) { + SEQ_LEQ(sack.end, highdata)) { sack_blocks[num_sack_blks++] = sack; } } @@ -838,7 +842,7 @@ * the ACK for a FIN is outstanding. */ tcp_seq highdata = tp->snd_max; - if (tp->t_flags & TF_SENTFIN) + if (__predict_false(tp->t_flags & TF_SENTFIN)) highdata--; if (th->th_ack != highdata) (void)tcp_sackhole_insert(tp, SEQ_MAX(th->th_ack, Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c +++ sys/netinet/tcp_subr.c @@ -2933,6 +2933,8 @@ tp->snd_nxt = tp->snd_una; tcp_free_sackholes(tp); tp->snd_recover = tp->snd_max; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + tp->snd_recover--; if (tp->t_flags & TF_SACK_PERMIT) EXIT_FASTRECOVERY(tp->t_flags); tp->t_fb->tfb_tcp_output(tp); Index: sys/netinet/tcp_timer.c =================================================================== --- sys/netinet/tcp_timer.c +++ sys/netinet/tcp_timer.c @@ -865,6 +865,8 @@ } tp->snd_nxt = tp->snd_una; tp->snd_recover = tp->snd_max; + if (__predict_false(tp->t_flags & TF_SENTFIN)) + tp->snd_recover--; /* * Force a segment to be sent. */