0

问题更新:除了下面的问题,似乎我们使用 Linux PLPMTUD 机制的客户端/服务器应用程序获得了太大的路径 MTU。有没有人看到这一点,即实际路径 MTU 为 1500,但getsockopt()返回TCP_MAXSEG端点的 MTU:s,在我们的例子中为 3000?我曾尝试使用 ethtool 切换 GRO、GSO 和 TSO,但错误仍然存​​在。正常 ping 只能设法通过 1472 字节或更小的数据包。另外值得一提的是 PLPMTUD 非常适合较小的 MTU:s。例如,w 个端点为 1500 MTU,中间路由器的一个接口设置为例如 1200 MTU,内核 TCP 探测并报告正确TCP_MAXSEG(1200 - 标头)。

我在应用程序中使用符合 Linux RFC4821 的分组层路径 MTU 发现。基本上,客户端在 TCP 套接字上执行 setsockopt:

setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &sopt, sizeof(sopt));

选项值设置为IP_PMTUDISC_PROBE. setsockopt()不返回错误。

客户端将大的 tcp 数据包发送到丢弃服务器,并且路径 MTU 由 Linux 内核校准 - tcpdump 显示正在发送设置了 DF 位的 tcp 数据包,数据包大小会变化,直到内核知道路径 MTU。但是,要让它在另一个方向上工作(监听服务器接受:来自客户端的连接,发送数据并在从服务器到客户端的方向校准 PMTU)我必须为 tcp 路径 mtu 发现设置全局选项,/proc/sys/net/ipv4/tcp_mtu_probing. 如果我不这样做,服务器将愚蠢地继续发送太大的数据包,这些数据包会被中间路由器丢弃而没有返回 ICMP。两个端点都将 MTU 设置为 3000,而中间跃点的 MTU 设置为 1500。

我希望有人知道出了什么问题。如果需要更多信息,请告诉我,我会编辑问题。Linux 内核 4.2.0 和 3.19.0 都存在问题,它们都是库存的 Kubuntu LTS 内核。(x86/x86-64)

在反向发送数据之前,我确实在所有接受:ed 套接字上设置了相同的套接字选项服务器端。

4

1 回答 1

0

FWIW,我找到了问题的解决方法/解决方案,将进行更多测试,但在这里简要描述我的发现,以防它帮助其他人。

通过在我的程序执行期间在系统范围内启用它,然后再次禁用它,解决了无法为每个套接字设置路径 mtu 发现的问题。

第二个问题,getsockopt TCP_MAXSEG 返回的路径 mtu 不正确,通过等待已发送 TCP 数据的 TCP ACK 得到修复,同样使用 getsockopt (tcp_info.tcpi_unacked)。这样,我可以确定在获得 TCP_MAXSEG 之前探测已经完成。

最后,在 2015 年 3 月,有一个用于提高路径 mtu 探测准确性的补丁集并入主线 Linux 内核。如果没有这些补丁,探测将非常不精确。Patchset 是 4.1.y 系列内核及更高版本的一部分。

于 2016-04-25T19:32:07.090 回答