When running tests over higher speed links, the new 2.6 Dynamic Receiver Sizing
code doesn't increase the window large enough. The problem is that the window
clamp restricts the allowed window to the socket receive buffer size (85k)
Easiest fix is to not restrict window clamp if we want to dynamic receiver stuff.
This is what web100 did.
Thanks to John Heffner for finding this.
Signed-off-by: Stephen Hemminger <redacted>
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c 2004-06-07 12:45:49 -07:00
+++ b/net/ipv4/tcp_input.c 2004-06-07 12:45:49 -07:00
@@ -300,7 +300,6 @@
static void tcp_init_buffer_space(struct sock *sk)
{
struct tcp_opt *tp = tcp_sk(sk);
- int maxwin;
if (!(sk->sk_userlocks & SOCK_RCVBUF_LOCK))
tcp_fixup_rcvbuf(sk);@@ -309,22 +308,24 @@
tp->rcvq_space.space = tp->rcv_wnd;
- maxwin = tcp_full_space(sk);
+ if (!sysctl_tcp_moderate_rcvbuf) {
+ int maxwin = tcp_full_space(sk);
- if (tp->window_clamp >= maxwin) {
- tp->window_clamp = maxwin;
+ if (tp->window_clamp >= maxwin) {
+ tp->window_clamp = maxwin;
- if (sysctl_tcp_app_win && maxwin > 4 * tp->advmss)
- tp->window_clamp = max(maxwin -
- (maxwin >> sysctl_tcp_app_win),
- 4 * tp->advmss);
+ if (sysctl_tcp_app_win && maxwin > 4 * tp->advmss)
+ tp->window_clamp = max(maxwin -
+ (maxwin >> sysctl_tcp_app_win),
+ 4 * tp->advmss);
+ }
+
+ /* Force reservation of one segment. */
+ if (sysctl_tcp_app_win &&
+ tp->window_clamp > 2 * tp->advmss &&
+ tp->window_clamp + tp->advmss > maxwin)
+ tp->window_clamp = max(2 * tp->advmss, maxwin - tp->advmss);
}
-
- /* Force reservation of one segment. */
- if (sysctl_tcp_app_win &&
- tp->window_clamp > 2 * tp->advmss &&
- tp->window_clamp + tp->advmss > maxwin)
- tp->window_clamp = max(2 * tp->advmss, maxwin - tp->advmss);
tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp);
tp->snd_cwnd_stamp = tcp_time_stamp;
On Mon, 7 Jun 2004 13:30:56 -0700
Stephen Hemminger [off-list ref] wrote:
When running tests over higher speed links, the new 2.6 Dynamic Receiver Sizing
code doesn't increase the window large enough. The problem is that the window
clamp restricts the allowed window to the socket receive buffer size (85k)
Easiest fix is to not restrict window clamp if we want to dynamic receiver stuff.
This is what web100 did.
Thanks to John Heffner for finding this.
This turns off all tcp_app_win semantics, are you sure that
tcp_app_win makes no sense when doing dynamic receive buffer
sizing? I think we should still factor it in, perhaps dynamically,
during rcvbuf growth.
As a followup I've put the following into my tree after discussing
some things with Stephen. He will do some of his tests to make
sure this fixes things as it should.
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/06/10 21:53:15-07:00 davem@nuts.davemloft.net
# [TCP]: Receive buffer moderation fixes.
#
# 1) Make window clamp follow receive buffer growth so it
# does not limit window advertisements. Noticed by John
# Heffner and Stephen Hemminger.
# 2) Fix rcvmem calculation such that tcp_adv_win_scale is
# taken into account.
#
# net/ipv4/tcp_input.c
# 2004/06/10 21:52:43-07:00 davem@nuts.davemloft.net +9 -1
# [TCP]: Receive buffer moderation fixes.
#
# 1) Make window clamp follow receive buffer growth so it
# does not limit window advertisements. Noticed by John
# Heffner and Stephen Hemminger.
#
# 2) Fix rcvmem calculation such that tcp_adv_win_scale is
# taken into account.
#
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c 2004-06-10 21:55:14 -07:00
+++ b/net/ipv4/tcp_input.c 2004-06-10 21:55:14 -07:00
@@ -463,6 +463,8 @@
tp->rcvq_space.space = space;
if (sysctl_tcp_moderate_rcvbuf) {
+ int new_clamp = space;
+
/* Receive space grows, normalize in order to
* take into account packet headers and sk_buff
* structure overhead.@@ -472,10 +474,16 @@
space = 1;
rcvmem = (tp->advmss + MAX_TCP_HEADER +
16 + sizeof(struct sk_buff));
+ while (tcp_win_from_space(rcvmem) < tp->advmss)
+ rcvmem += 128;
space *= rcvmem;
space = min(space, sysctl_tcp_rmem[2]);
- if (space > sk->sk_rcvbuf)
+ if (space > sk->sk_rcvbuf) {
sk->sk_rcvbuf = space;
+
+ /* Make the window clamp follow along. */
+ tp->window_clamp = new_clamp;
+ }
}
}