我正在通过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),从而验证了我的流量捕获。
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
,则在所有情况下它将是有效值。 - mvdssysctl_tcp_rmem[2]
而不是rcv_wscale
。由于我们都不清楚rcv_wscale
是否在其他地方使用,我已经向linux-man@vger.kernel.org
发送了电子邮件,请求澄清手册。 (继续下一条评论;无论如何,你的答案肯定符合我的奖励,谢谢!) - nh2iperf3
中发现了这个问题 https://github.com/esnet/iperf/issues/356 ,这让我感到困惑(iperf3 -w
似乎没有起作用):https://github.com/esnet/iperf/issues/356 - nh2