TCP接收窗口大小高于net.core.rmem_max

13

我正在通过10Gbit连接将两台服务器之间运行iperf测量。我试图将我观察到的最大窗口大小与系统配置参数进行关联。

特别地,我观察到最大窗口大小为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)调用中请求的缓冲区大小分配两倍的空间,因此succeeding getsockopt(2)调用将不会返回与在setsockopt(2)调用中请求的缓冲区大小相同的缓冲区大小。 TCP使用额外的空间进行管理和内部内核结构,并且/ proc文件值反映与实际TCP窗口相比更大的大小。

然而,第二个值net.core.rmem_max表明最大接收窗口大小不能超过208 KiB。 根据man tcp,这应该是硬性限制:

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

那么,为什么我观察到的最大窗口大小比net.core.rmem_max中指定的窗口大小要大呢?

NB: 我还计算了带宽延迟乘积: window_size = Bandwidth x RTT,约为3 MiB(10 Gbps @ 2毫秒RTT),从而验证了我的流量捕获。

2个回答

18

快速搜索结果如下:

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将在除设置SO_RCVBUF(其检查可以使用SO_RCVBUFFORCE绕过)外的所有情况下覆盖net.core.rmem_max


...你可以得出结论,更大的net.ipv4.tcp_rmem将在所有情况下覆盖net.core.rmem_max,除非设置SO_RCVBUF - 我还不清楚是否在所有情况下都发生这种情况:在您发布的函数中,max_t(u32,sysctl_tcp_rmem [2],sysctl_rmem_max)确定rcv_wscale,然后用于设置窗口大小。因此,两个值中的最大值应在整个过程中使用。但是,我无法通过实验确认:将net.core.rmem_max设置为非常大并不会使窗口大小超过tcp_rmem的最大值。 - nh2
1
我并没有说反过来也成立,我更倾向于认为一个大的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,则在所有情况下它将是有效值。 - mvds
你说得对,许多地方如这里这里直接引用了sysctl_tcp_rmem[2]而不是rcv_wscale。由于我们都不清楚rcv_wscale是否在其他地方使用,我已经向linux-man@vger.kernel.org发送了电子邮件,请求澄清手册。 (继续下一条评论;无论如何,你的答案肯定符合我的奖励,谢谢!) - nh2
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - nh2
1
通过您的解释,我也在 iperf3 中发现了这个问题 https://github.com/esnet/iperf/issues/356 ,这让我感到困惑(iperf3 -w 似乎没有起作用):https://github.com/esnet/iperf/issues/356 - nh2
显示剩余4条评论

1

2
我已经开始了一个悬赏,以找出“man tcp”是否真的有错。 - nh2
在@mvds的出色回答之后,我已经在这里报告了显然的手册页错误:https://bugzilla.kernel.org/show_bug.cgi?id=209327 - nh2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接