diff options
author | ps <ps@FreeBSD.org> | 2005-06-06 19:46:53 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2005-06-06 19:46:53 +0000 |
commit | 10d5de225b37670a3525c2638977fe531c71c7e9 (patch) | |
tree | 809c1a0e3af79983c101068036816337f8a1e503 /sys/netinet/tcp_sack.c | |
parent | 046434d141f279849e3cd8d0925ca6978961dd1b (diff) | |
download | FreeBSD-src-10d5de225b37670a3525c2638977fe531c71c7e9.zip FreeBSD-src-10d5de225b37670a3525c2638977fe531c71c7e9.tar.gz |
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.
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 28c6d8a..7708e9d 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); } |