2015-07-21 696 views
5

我正在运行iperf两台服务器之间的测量,通过10Gbit链接连接。我试图将我观察到的最大窗口大小与系统配置参数相关联。TCP接收窗口大小高于net.core.rmem_max

特别是,我观察到最大窗口大小为3 MiB。但是,我无法在系统文件中找到相应的值。

通过运行sysctl -a我得到以下值:

net.ipv4.tcp_rmem = 4096  87380 6291456 
net.core.rmem_max = 212992 

第一个值告诉我们,最大接收窗口大小为6 MIB。但是,TCP倾向于分配两倍的请求大小,所以最大接收器窗口大小应该为3 MiB,正如我测量的那样。从man tcp

注意,TCP实际分配在setsockopt的(2)调用请求缓冲区大小的两倍,因此后续的getsockopt(2)调用不会如要求返回缓冲区的大小相同setsockopt(2)调用。 TCP使用额外的空间用于管理目的和内部内核结构,并且与实际的TCP窗口相比,/ proc文件值反映了更大的大小。

但是,第二个值net.core.rmem_max指出最大接收器窗口大小不能超过208 KiB。这被认为是硬限制,根据man tcp

tcp_rmem 最大值:由每个TCP套接字中使用的接收缓冲器的最大尺寸。此值不会覆盖全球net.core.rmem_max。这不用于限制套接字上使用SO_RCVBUF声明的接收缓冲区的大小。

那么,怎么来,我观察到的最大窗口尺寸大于net.core.rmem_max中指定的最大窗口尺寸?

NB:我也计算出的带宽-延迟产物:window_size = Bandwidth x RTT大约是3 MIB(10 Gbps的@ 2毫秒RTT),从而验证我的流量捕获。

回答

4

快速搜索止跌回升:

https://github.com/torvalds/linux/blob/4e5448a31d73d0e944b7adb9049438a09bc332cb/net/ipv4/tcp_output.c

void tcp_select_initial_window()

if (wscale_ok) { 
    /* Set window scaling on max possible window 
    * See RFC1323 for an explanation of the limit to 14 
    */ 
    space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); 
    space = min_t(u32, space, *window_clamp); 
    while (space > 65535 && (*rcv_wscale) < 14) { 
     space >>= 1; 
     (*rcv_wscale)++; 
    } 
} 

max_t需要的参数值越高。所以更大的价值在这里优先。

sysctl_rmem_max的一个其他参考用于将参数限制为SO_RCVBUF(在net/core/sock.c中)。

所有其他tcp代码仅指sysctl_tcp_rmem

所以不看更深的代码,你可以得出结论,一个更大的net.ipv4.tcp_rmem将覆盖在所有情况下net.core.rmem_max设置SO_RCVBUF(其检查可使用SO_RCVBUFFORCE绕过)

+0

'...你可以得出结论:在所有情况下,除了设置SO_RCVBUF之外,更大的net.ipv4.tcp_rmem都会覆盖net.core.rmem_max - 我不清楚这是否在所有情况下都发生:在你发布的函数,'max_t(u32,sysctl_tcp_rmem [2],sysctl_rmem_max)'确定'rcv_wscale',然后用它来设置窗口大小。所以应该使用这两个值的最大值。但是,我无法通过实验确认:将'net.core.rmem_max'设置得非常大不会使窗口大小超过tcp_rmem的最大值。 – nh2

+0

我没有说反过来是真的(!),我宁愿期待一个大的'net.core.rmem_max'没有太大的影响,因为所有其他代码只引用'net.ipv4 .tcp_rmem';对'net.core.rmem_max'的引用在一个名为'tcp_select_initial_window'的例程中只执行一次*。但是在选择初始窗口之后,我没有关注所有的内部结构,看看'rcv_wscale'完成了什么。我只能从表面代码扫描中得出结论:如果net.ipv4.tcp_rmem大于'net.core.rmem_max',那么在所有情况下'net.ipv4.tcp_rmem'都是有效的值。 – mvds

+0

你是对的,很多地方如[this](https://github.com/torvalds/linux/blob/34229b277480f46c1e9a19f027f30b074512e68b/net/ipv4/tcp_input.c#L455)和[here](https:// github。 com/torvalds/linux/blob/34229b277480f46c1e9a19f027f30b074512e68b/net/ipv4/tcp_input.c#L607)直接指代'sysctl_tcp_rmem [2]'而不是'rcv_wscale'。由于它对我们两个人来说都是不透明的,所以在其他地方是否使用了'rcv_wscale',我刚刚发送了一封电子邮件到'linux-man @ vger.kernel.org',并要求澄清man page。 (继续下一个评论;在任何情况下,你的答案肯定会触及我的赏金,thx!) – nh2