问题更新:除了下面的问题之外,似乎我们的客户机/服务器应用程序使用Linux PLPMTUD机制得到了太大的路径MTU。有没有人看到过,即实际路径MTU是1500,但是getsockopt w TCP_MAXSEG返回端点的MTU:s,在我们的例子中是3000?我试过用ethtool旋转GRO、GSO和TSO,但错误仍然存在。普通ping只能处理1472字节或更小的数据包。另外值得一提的是,PLPMTUD非常适合较小的MTU:s。例如,w端点位于1500 MTU,中间路由器的一个接口设置为1200 MTU,内核TCP探测并报告正确的TCP_MAXSEG(1200-headers)。
我在应用程序中使用符合Linux RFC4821的packetization layer path MTU发现。基本上,客户端在TCP套接字上执行setsockopt:
setsockopt(fd、SOL_IP、IP_MTU_DISCOVER和sopt、sizeof(sopt))
将选项值设置为IP PMTUDISC U PROBE。setsockopt不返回错误。
客户端向discard服务器发送大的tcp数据包,路径MTU由Linux内核校准-tcpdump显示发送DF位设置的tcp数据包,数据包大小变化,直到内核知道路径MTU。但是,要使它在另一个方向上工作(侦听服务器接受:从客户端建立连接,从服务器向客户端发送数据并校准PMTU),我必须为tcp path mtu discovery设置全局选项,/proc/sys/net/ipv4/tcpu mtu probing。如果我不这样做,服务器将愚蠢地继续发送太大的数据包,这些数据包将被中间路由器丢弃,而ICMP不会被发送回来。两个端点的MTU设置为3000,而中间跃点的MTU设置为1500。
我希望有人知道出了什么问题。如果需要更多的信息,让我知道,我编辑的问题。Linux内核4.2.0和3.19.0都存在问题,它们都是股票KuBuntu-LTS内核。(x86/x86-64)
在反向发送数据之前,我也在所有accept:ed套接字上设置了相同的套接字选项server-side。

最佳答案

FWIW,我已经找到了解决问题的方法/解决方案,将进行更多的测试,但是在这里简要描述一下我的发现,以防它帮助了其他人。
无法为每个套接字设置路径mtu发现的问题已被修复,通过在我的程序执行期间在系统范围内启用它,然后再次禁用。
第二个问题是getsockopt TCP_MAXSEG返回的路径mtu不正确,通过等待发送的TCP数据的TCP ACK,也使用getsockopt(TCP_info.tcpi_unacked)解决了这个问题。这样,在获取TCP_MAXSEG之前,我可以确定探测已经完成。
最后,在2015年3月,有一个补丁集用于提高路径mtu探测精度,并合并到主线Linux内核中。没有这些补丁,探测是非常不精确的。Patchset是4.1.y系列内核和更高版本的一部分。

关于linux - TCP_MAXSEG不正确? (是:如果使用setsockopt()请求,则Linux路径MTU探测不适用于accept():ed套接字),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36740276/

10-13 01:07