summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_sack.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2004-10-05 18:36:24 +0000
committerps <ps@FreeBSD.org>2004-10-05 18:36:24 +0000
commitc8e4aa1cd58a20597b74285a3cc35ea24ba5c47c (patch)
treebcb9cd585361024879ec2c577e898534dec0d79d /sys/netinet/tcp_sack.c
parent9536269a6d161e34a72dee84f6df6b4183f51be8 (diff)
downloadFreeBSD-src-c8e4aa1cd58a20597b74285a3cc35ea24ba5c47c.zip
FreeBSD-src-c8e4aa1cd58a20597b74285a3cc35ea24ba5c47c.tar.gz
- Estimate the amount of data in flight in sack recovery and use it
to control the packets injected while in sack recovery (for both retransmissions and new data). - Cleanups to the sack codepaths in tcp_output.c and tcp_sack.c. - Add a new sysctl (net.inet.tcp.sack.initburst) that controls the number of sack retransmissions done upon initiation of sack recovery. Submitted by: Mohan Srinivasan <mohans@yahoo-inc.com>
Diffstat (limited to 'sys/netinet/tcp_sack.c')
-rw-r--r--sys/netinet/tcp_sack.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 1cf44f2..e30e9d6 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -164,6 +164,11 @@ struct tcphdr tcp_savetcp;
extern struct uma_zone *sack_hole_zone;
+SYSCTL_NODE(_net_inet_tcp, OID_AUTO, sack, CTLFLAG_RW, 0, "TCP SACK");
+int tcp_do_sack = 1;
+SYSCTL_INT(_net_inet_tcp_sack, OID_AUTO, enable, CTLFLAG_RW,
+ &tcp_do_sack, 0, "Enable/Disable TCP SACK support");
+
/*
* This function is called upon receipt of new valid data (while not in header
* prediction mode), and it updates the ordered list of sacks.
@@ -486,18 +491,19 @@ tcp_sack_partialack(tp, th)
{
INP_LOCK_ASSERT(tp->t_inpcb);
u_long ocwnd = tp->snd_cwnd;
+ int sack_bytes_rexmt = 0;
callout_stop(tp->tt_rexmt);
tp->t_rtttime = 0;
/*
- * Set snd_cwnd to one segment beyond acknowledged offset
- * (tp->snd_una has not yet been updated when this function is called.)
- */
- /*
- * Should really be
- * min(tp->snd_cwnd, tp->t_maxseg + (th->th_ack - tp->snd_una))
+ * Set cwnd so we can send one more segment (either rexmit based on
+ * scoreboard or new segment). Set cwnd to the amount of data
+ * rexmitted from scoreboard plus the amount of new data transmitted
+ * in this sack recovery episode plus one segment.
*/
- tp->snd_cwnd = tp->t_maxseg + (th->th_ack - tp->snd_una);
+ (void)tcp_sack_output(tp, &sack_bytes_rexmt);
+ tp->snd_cwnd = sack_bytes_rexmt + (tp->snd_nxt - tp->sack_newdata) +
+ tp->t_maxseg;
tp->t_flags |= TF_ACKNOW;
(void) tcp_output(tp);
tp->snd_cwnd = ocwnd;
@@ -529,29 +535,29 @@ tcp_print_holes(struct tcpcb *tp)
* NULL otherwise.
*/
struct sackhole *
-tcp_sack_output(struct tcpcb *tp)
+tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt)
{
- struct sackhole *p;
+ struct sackhole *p = NULL;
INP_LOCK_ASSERT(tp->t_inpcb);
if (!tp->sack_enable)
return (NULL);
- p = tp->snd_holes;
- while (p) {
+ *sack_bytes_rexmt = 0;
+ for (p = tp->snd_holes; p ; p = p->next) {
if (SEQ_LT(p->rxmit, p->end)) {
if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */
- p = p->next;
continue;
}
#ifdef TCP_SACK_DEBUG
if (p)
tcp_print_holes(tp);
#endif
- return (p);
+ *sack_bytes_rexmt += (p->rxmit - p->start);
+ break;
}
- p = p->next;
+ *sack_bytes_rexmt += (p->rxmit - p->start);
}
- return (NULL);
+ return (p);
}
/*
@@ -588,4 +594,3 @@ tcp_sack_adjust(struct tcpcb *tp)
tp->snd_nxt = tp->rcv_lastsack;
return;
}
-
OpenPOWER on IntegriCloud