我目前正在构建我的 DIY 路由器的新版本 - 新系统有一对 10 gig 端口。我在 R68S U1 上运行 ubuntu 23.04
最初,在我知道可以处理 10 gig 线路速度的系统之间使用 iperf2 进行速度测试时,我得到了 5 gig 速度。华硕的设备指南之一建议使用 iperf 在 800k 下进行测试
geek@router-t1:~$ iperf -s -w 800k
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 416 KByte (WARNING: requested 781 KByte)
------------------------------------------------------------
[ 1] local 10.0.0.1 port 5001 connected with 10.0.0.2 port 52191
[ ID] Interval Transfer Bandwidth
[ 1] 0.0000-60.0461 sec 35.0 GBytes 5.01 Gbits/sec
有趣的是,这表明我的 TCP 窗口尺寸较小,而这正是华硕警告的内容。
Windows 客户端永远不会发生这种情况,只有 Linux 客户端才会发生这种情况……这很奇怪,但可能是另一个问题
添加以下行 - 按照此处的建议
net.core.wmem_max=4194304
net.core.rmem_max=12582912
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 87380 4194304
结果是基准的两倍
geek@router-t1:~$ iperf -s -w 800k -B 10.0.0.1
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 1.53 MByte (WARNING: requested 781 KByte)
------------------------------------------------------------
[ 1] local 10.0.0.1 port 5001 connected with 10.0.0.2 port 57480
[ ID] Interval Transfer Bandwidth
[ 1] 0.0000-60.0443 sec 69.2 GBytes 9.90 Gbits/sec
我知道这会调整套接字接收缓冲区和新创建的套接字的缓冲区大小 - IBM 对他们在这里所做的事情有一个很好的解释
我如何计算出给定系统的适当大小,以及为什么这会产生如此巨大的效果?
为了获得最大吞吐量,TCP 窗口大小必须足够大,以允许发送方“保持管道满”,这意味着它需要能够以链路可以承受的速度继续发送全尺寸的数据段,并且持续足够长的时间才能获得确认第一个数据包。该 Ack 时间将是该网络路径的往返时间 (RTT),这是测量的
ping(8)
值,但请注意,在空闲网络上通过 ping 测量的 RTT 可能会低于 TCP 发送方在保持10Gbps 链路已满。我们通常将此计算称为“带宽 x 延迟乘积”(BDP)。因此,乘以您的带宽(以每秒位数为单位),再乘以您的 RTT(以秒为单位)。这允许秒数被抵消,留下在任何给定时间可能需要“飞行”(“在网络中”、“在管道中”)的位数,以保持管道充满。
因此,使用我通常在以太网 LAN 上看到的 10Gbps 和 0.3ms 典型有线以太网 LAN 空闲 ping 时间,这将是 10,000,000,000 位/秒 x 0.0003 秒 = 3,000,000 位 = 大约 366 KibiBytes。
因此,初步估计,您的原始 416KiByte TCP 窗口应该能够实现全速性能。这表明,对于满载时 10Gbps 链路上的 TCP 实际情况,我对 0.3 毫秒 RTT 的估计较低。
如果我将 RTT 估计值修改为 1ms,则 BDP 为 1.2MiBytes,这更符合在您调整 sysctls 以为其提供更多空间后,Linux TCP 堆栈在成功示例中自动缩放窗口的 1.53MiByte 大小规模化。
为每个 TCP 连接提供几兆字节的 RAM 作为接收窗口对于 LAN 上的个人计算机来说是没问题的,但对于必须同时处理数百或数千个 TCP 连接的繁忙服务器来说可能会出现问题。你可能很快就会耗尽内存。这就是大多数现代 TCP 实现都内置并默认启用窗口自动缩放算法的部分原因,但受到 sysctl 的限制。