【问题标题】:TCP receiving window size higher than net.core.rmem_maxTCP 接收窗口大小高于 net.core.rmem_max
【发布时间】:2020-05-25 02:57:43
【问题描述】:

我正在通过 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) 调用中请求的缓冲区大小的两倍,因此后续的 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 中指定的最大窗口大小?

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

【问题讨论】:

    标签: linux performance tcp iperf congestion-control


    【解决方案1】:

    快速搜索出现了:

    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 绕过其检查)

    【讨论】:

    • ... you can conclude that a bigger net.ipv4.tcp_rmem will override net.core.rmem_max in all cases except when setting SO_RCVBUF - 我还不清楚这是否在所有情况下都发生:在您发布的函数中,max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max) 确定rcv_wscale,然后用于设置窗口大小。因此,应彻底使用这两个值中的最大值。但是,我无法通过实验确认:将net.core.rmem_max 设置为非常大不会将窗口大小增加到超过tcp_rmem 的最大值。
    • 我并没有说反之亦然(!),我宁愿期望大的net.core.rmem_max 不会产生太大影响,正如您所观察到的那样,因为所有其他代码仅引用@ 987654342@;在名为tcp_select_initial_window 的例程中,对net.core.rmem_max 的引用只进行一次。但是我还没有查看所有内部结构,看看在选择初始窗口后rcv_wscale 做了什么。我可以从表面的代码扫描中得出结论,如果net.ipv4.tcp_rmem 大于net.core.rmem_max,那么它在所有情况下都是有效值。
    • 你说得对,thishere等很多地方直接引用sysctl_tcp_rmem[2]而不是rcv_wscale。由于rcv_wscale 是否在其他任何地方使用对我们双方来说都是不透明的,我刚刚向linux-man@vger.kernel.org 发送了一封电子邮件,并要求澄清手册页。 (在下一条评论中继续;无论如何,你的回答肯定会打到我的赏金,谢谢!)
    • 回到正题,可能man page中的"This value does not override the global net.core.rmem_max."实际上被解释为"This value does not override the global net.core.rmem_max to the extent that it does not define the upper users can set with SO_RCVBUF. It does, however, override net.core.rmem_max if SO_RCVBUF is not used."。这与我们的调查结果一致,但如果这是真的,我觉得措辞很不幸(因此我的电子邮件发给linux-man)。
    • 根据你的解释,我也在iperf3github.com/esnet/iperf/issues/356发现了这个让我很困惑的问题(iperf3 -w似乎什么都没做):github.com/esnet/iperf/issues/356
    【解决方案2】:

    net.ipv4.tcp_rmem根据https://serverfault.com/questions/734920/difference-between-net-core-rmem-max-and-net-ipv4-tcp-rmem优先net.core.rmem_max

    tcp 设置似乎优先于常见的 max 设置


    但我同意你的说法,这似乎与man tcp 中写的内容相冲突,我可以重现你的发现。也许文档是错误的?请了解并发表评论!

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多