12

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

特别是,我观察到最大窗口大小为 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),从而验证了我的流量捕获。

4

2 回答 2

17

快速搜索出现了:

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_maxSO_RCVBUFSO_RCVBUFFORCE

于 2016-02-16T16:45:30.980 回答
1

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

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


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

于 2016-02-16T16:28:48.670 回答