diff options
author | Paul Saab <ps@FreeBSD.org> | 2005-06-06 19:46:53 +0000 |
---|---|---|
committer | Paul Saab <ps@FreeBSD.org> | 2005-06-06 19:46:53 +0000 |
commit | db4b83fe49ed5211bae215d78827ed9014285ea5 (patch) | |
tree | 809c1a0e3af79983c101068036816337f8a1e503 /sys/netinet/tcp_sack.c | |
parent | 75190ff847f8a3e07a80297040bb14dced299516 (diff) | |
download | src-db4b83fe49ed5211bae215d78827ed9014285ea5.tar.gz src-db4b83fe49ed5211bae215d78827ed9014285ea5.zip |
Fix for a bug in the change that walks the scoreboard backwards from
the tail (in tcp_sack_option()). The bug was caused by incorrect
accounting of the retransmitted bytes in the sackhint.
Reported by: Kris Kennaway.
Submitted by: Noritoshi Demizu.
Notes
Notes:
svn path=/head/; revision=147061
Diffstat (limited to 'sys/netinet/tcp_sack.c')
-rw-r--r-- | sys/netinet/tcp_sack.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index 28c6d8a4d420..7708e9de7ddc 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -508,8 +508,6 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen) cur->start = sblkp->end; cur->rxmit = SEQ_MAX(cur->rxmit, cur->start); } - /* Go to the previous hole. */ - cur = TAILQ_PREV(cur, sackhole_head, scblink); } else { /* Data acks at least the end of hole */ if (SEQ_GEQ(sblkp->end, cur->end)) { @@ -535,10 +533,17 @@ tcp_sack_option(struct tcpcb *tp, struct tcphdr *th, u_char *cp, int optlen) cur->end); } } - /* Go to the previous sack block. */ - sblkp--; } tp->sackhint.sack_bytes_rexmit += (cur->rxmit - cur->start); + /* + * Testing sblkp->start against cur->start tells us whether + * we're done with the sack block or the sack hole. + * Accordingly, we advance one or the other. + */ + if (SEQ_LEQ(sblkp->start, cur->start)) + cur = TAILQ_PREV(cur, sackhole_head, scblink); + else + sblkp--; } return (0); } |