summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2005-06-06 19:46:53 +0000
committerps <ps@FreeBSD.org>2005-06-06 19:46:53 +0000
commit10d5de225b37670a3525c2638977fe531c71c7e9 (patch)
tree809c1a0e3af79983c101068036816337f8a1e503
parent046434d141f279849e3cd8d0925ca6978961dd1b (diff)
downloadFreeBSD-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.
-rw-r--r--sys/netinet/tcp_sack.c13
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);
}
OpenPOWER on IntegriCloud