diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 29a320f1268a..4c2a4903767c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1046,7 +1046,7 @@ tcp_input(struct mbuf *m, int off0) if (to.to_flags & TOF_MSS) tcp_mss(tp, to.to_mss); if (tp->sack_enable) { - if (!(to.to_flags & TOF_SACK)) + if (!(to.to_flags & TOF_SACKPERM)) tp->sack_enable = 0; else tp->t_flags |= TF_SACK_PERMIT; @@ -1098,7 +1098,8 @@ tcp_input(struct mbuf *m, int off0) ((!tcp_do_newreno && !tp->sack_enable && tp->t_dupacks < tcprexmtthresh) || ((tcp_do_newreno || tp->sack_enable) && - !IN_FASTRECOVERY(tp) && to.to_nsacks == 0 && + !IN_FASTRECOVERY(tp) && + (to.to_flags & TOF_SACK) == 0 && TAILQ_EMPTY(&tp->snd_holes)))) { KASSERT(headlocked, ("headlocked")); INP_INFO_WUNLOCK(&tcbinfo); @@ -1848,7 +1849,8 @@ tcp_input(struct mbuf *m, int off0) goto dropafterack; } if (tp->sack_enable && - (to.to_nsacks > 0 || !TAILQ_EMPTY(&tp->snd_holes))) + ((to.to_flags & TOF_SACK) || + !TAILQ_EMPTY(&tp->snd_holes))) tcp_sack_doack(tp, &to, th->th_ack); if (SEQ_LEQ(th->th_ack, tp->snd_una)) { if (tlen == 0 && tiwin == tp->snd_wnd) { @@ -2657,11 +2659,12 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags) continue; if (!tcp_do_sack) continue; - to->to_flags |= TOF_SACK; + to->to_flags |= TOF_SACKPERM; break; case TCPOPT_SACK: if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0) continue; + to->to_flags |= TOF_SACK; to->to_nsacks = (optlen - 2) / TCPOLEN_SACK; to->to_sacks = cp + 2; tcpstat.tcps_sack_rcv_blocks++; diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 29a320f1268a..4c2a4903767c 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -1046,7 +1046,7 @@ tcp_input(struct mbuf *m, int off0) if (to.to_flags & TOF_MSS) tcp_mss(tp, to.to_mss); if (tp->sack_enable) { - if (!(to.to_flags & TOF_SACK)) + if (!(to.to_flags & TOF_SACKPERM)) tp->sack_enable = 0; else tp->t_flags |= TF_SACK_PERMIT; @@ -1098,7 +1098,8 @@ tcp_input(struct mbuf *m, int off0) ((!tcp_do_newreno && !tp->sack_enable && tp->t_dupacks < tcprexmtthresh) || ((tcp_do_newreno || tp->sack_enable) && - !IN_FASTRECOVERY(tp) && to.to_nsacks == 0 && + !IN_FASTRECOVERY(tp) && + (to.to_flags & TOF_SACK) == 0 && TAILQ_EMPTY(&tp->snd_holes)))) { KASSERT(headlocked, ("headlocked")); INP_INFO_WUNLOCK(&tcbinfo); @@ -1848,7 +1849,8 @@ tcp_input(struct mbuf *m, int off0) goto dropafterack; } if (tp->sack_enable && - (to.to_nsacks > 0 || !TAILQ_EMPTY(&tp->snd_holes))) + ((to.to_flags & TOF_SACK) || + !TAILQ_EMPTY(&tp->snd_holes))) tcp_sack_doack(tp, &to, th->th_ack); if (SEQ_LEQ(th->th_ack, tp->snd_una)) { if (tlen == 0 && tiwin == tp->snd_wnd) { @@ -2657,11 +2659,12 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags) continue; if (!tcp_do_sack) continue; - to->to_flags |= TOF_SACK; + to->to_flags |= TOF_SACKPERM; break; case TCPOPT_SACK: if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0) continue; + to->to_flags |= TOF_SACK; to->to_nsacks = (optlen - 2) / TCPOLEN_SACK; to->to_sacks = cp + 2; tcpstat.tcps_sack_rcv_blocks++; diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index dca7cd4148b6..39aa87ab8646 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -371,6 +371,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) int i, j, num_sack_blks; INP_LOCK_ASSERT(tp->t_inpcb); + KASSERT(to->to_flags & TOF_SACK, ("%s: SACK invalid", __func__)); num_sack_blks = 0; /*