summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_sack.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2005-11-21 19:22:10 +0000
committerps <ps@FreeBSD.org>2005-11-21 19:22:10 +0000
commit6b40ef55c34c5b06f335f63f127ff9eeccd79de1 (patch)
tree81bb756a5a50d98f4f02351ac5799e7c8af806af /sys/netinet/tcp_sack.c
parent2dad4e87ed16e0442e1532ad2aa2d71b0c37d3dc (diff)
downloadFreeBSD-src-6b40ef55c34c5b06f335f63f127ff9eeccd79de1.zip
FreeBSD-src-6b40ef55c34c5b06f335f63f127ff9eeccd79de1.tar.gz
Fix for a bug that causes SACK scoreboard corruption when the limit
on holes per connection is reached. Reported by: Patrik Roos Submitted by: Mohan Srinivasan Reviewed by: Raja Mukerji, Noritoshi Demizu
Diffstat (limited to 'sys/netinet/tcp_sack.c')
-rw-r--r--sys/netinet/tcp_sack.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 163e0a4..02ffdde 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -448,11 +448,26 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
* way of hole splitting in the while-loop below.
*/
temp = tcp_sackhole_insert(tp, tp->snd_fack,sblkp->start,NULL);
- if (temp == NULL)
- return;
- tp->snd_fack = sblkp->end;
- /* Go to the previous sack block. */
- sblkp--;
+ if (temp != NULL) {
+ tp->snd_fack = sblkp->end;
+ /* Go to the previous sack block. */
+ sblkp--;
+ } else {
+ /*
+ * We failed to add a new hole based on the current
+ * sack block. Skip over all the sack blocks that
+ * fall completely to the right of snd_fack and proceed
+ * to trim the scoreboard based on the remaining sack
+ * blocks. This also trims the scoreboard for th_ack
+ * (which is sack_blocks[0]).
+ */
+ while (sblkp >= sack_blocks &&
+ SEQ_LT(tp->snd_fack, sblkp->start))
+ sblkp--;
+ if (sblkp >= sack_blocks &&
+ SEQ_LT(tp->snd_fack, sblkp->end))
+ tp->snd_fack = sblkp->end;
+ }
} else if (SEQ_LT(tp->snd_fack, sblkp->end))
/* fack is advanced. */
tp->snd_fack = sblkp->end;
@@ -463,7 +478,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
* Since the incoming sack blocks are sorted, we can process them
* making one sweep of the scoreboard.
*/
- while (sblkp - sack_blocks >= 0 && cur != NULL) {
+ while (sblkp >= sack_blocks && cur != NULL) {
if (SEQ_GEQ(sblkp->start, cur->end)) {
/*
* SACKs data beyond the current hole.
OpenPOWER on IntegriCloud