diff options
author | John Heffner <jheffner@psc.edu> | 2006-10-18 23:36:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-10-18 23:36:48 -0400 |
commit | ae8064ac32d07f609114d73928cdef803be87134 (patch) | |
tree | a783594abc5ca2f795992664684ab46581625fac | |
parent | b52f070c9c3c09ed3b7f699280193aae7e25d816 (diff) |
[TCP]: Bound TSO defer time
This patch limits the amount of time you will defer sending a TSO segment
to less than two clock ticks, or the time between two acks, whichever is
longer.
On slow links, deferring causes significant bursts. See attached plots,
which show RTT through a 1 Mbps link with a 100 ms RTT and ~100 ms queue
for (a) non-TSO, (b) currnet TSO, and (c) patched TSO. This burstiness
causes significant jitter, tends to overflow queues early (bad for short
queues), and makes delay-based congestion control more difficult.
Deferring by a couple clock ticks I believe will have a relatively small
impact on performance.
Signed-off-by: John Heffner <jheffner@psc.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 20 |
2 files changed, 17 insertions, 5 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 0e058a2d1c6d..2d36f6db3706 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -342,6 +342,8 @@ struct tcp_sock { | |||
342 | 342 | ||
343 | unsigned long last_synq_overflow; | 343 | unsigned long last_synq_overflow; |
344 | 344 | ||
345 | __u32 tso_deferred; | ||
346 | |||
345 | /* Receiver side RTT estimation */ | 347 | /* Receiver side RTT estimation */ |
346 | struct { | 348 | struct { |
347 | __u32 rtt; | 349 | __u32 rtt; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f22536e32cb1..ca406157724c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1096 | u32 send_win, cong_win, limit, in_flight; | 1096 | u32 send_win, cong_win, limit, in_flight; |
1097 | 1097 | ||
1098 | if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) | 1098 | if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) |
1099 | return 0; | 1099 | goto send_now; |
1100 | 1100 | ||
1101 | if (icsk->icsk_ca_state != TCP_CA_Open) | 1101 | if (icsk->icsk_ca_state != TCP_CA_Open) |
1102 | return 0; | 1102 | goto send_now; |
1103 | |||
1104 | /* Defer for less than two clock ticks. */ | ||
1105 | if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1) | ||
1106 | goto send_now; | ||
1103 | 1107 | ||
1104 | in_flight = tcp_packets_in_flight(tp); | 1108 | in_flight = tcp_packets_in_flight(tp); |
1105 | 1109 | ||
@@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1115 | 1119 | ||
1116 | /* If a full-sized TSO skb can be sent, do it. */ | 1120 | /* If a full-sized TSO skb can be sent, do it. */ |
1117 | if (limit >= 65536) | 1121 | if (limit >= 65536) |
1118 | return 0; | 1122 | goto send_now; |
1119 | 1123 | ||
1120 | if (sysctl_tcp_tso_win_divisor) { | 1124 | if (sysctl_tcp_tso_win_divisor) { |
1121 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); | 1125 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); |
@@ -1125,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1125 | */ | 1129 | */ |
1126 | chunk /= sysctl_tcp_tso_win_divisor; | 1130 | chunk /= sysctl_tcp_tso_win_divisor; |
1127 | if (limit >= chunk) | 1131 | if (limit >= chunk) |
1128 | return 0; | 1132 | goto send_now; |
1129 | } else { | 1133 | } else { |
1130 | /* Different approach, try not to defer past a single | 1134 | /* Different approach, try not to defer past a single |
1131 | * ACK. Receiver should ACK every other full sized | 1135 | * ACK. Receiver should ACK every other full sized |
@@ -1133,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1133 | * then send now. | 1137 | * then send now. |
1134 | */ | 1138 | */ |
1135 | if (limit > tcp_max_burst(tp) * tp->mss_cache) | 1139 | if (limit > tcp_max_burst(tp) * tp->mss_cache) |
1136 | return 0; | 1140 | goto send_now; |
1137 | } | 1141 | } |
1138 | 1142 | ||
1139 | /* Ok, it looks like it is advisable to defer. */ | 1143 | /* Ok, it looks like it is advisable to defer. */ |
1144 | tp->tso_deferred = 1 | (jiffies<<1); | ||
1145 | |||
1140 | return 1; | 1146 | return 1; |
1147 | |||
1148 | send_now: | ||
1149 | tp->tso_deferred = 0; | ||
1150 | return 0; | ||
1141 | } | 1151 | } |
1142 | 1152 | ||
1143 | /* Create a new MTU probe if we are ready. | 1153 | /* Create a new MTU probe if we are ready. |