2016-04-20 38 views
0

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

我在应用程序中使用符合Linux RFC4821的打包层路径MTU发现。基本上,客户端不上的TCP套接字一个setsockopt的:

setsockopt的(FD,SOL_IP,IP_MTU_DISCOVER,& SOPT,的sizeof(SOPT)) 与选项值设置为IP_PMTUDISC_PROBE。 setsockopt不会返回错误。

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

我希望有人对错误发生了解。如果需要更多信息,请告诉我,并编辑问题。 Linux内核4.2.0和3.19.0都存在问题,都是库存Kubuntu LTS内核。 (x86/x86-64)

我在所有accept:ed套接字上设置了相同的套接字选项服务器端,然后再反向发送数据。

+0

尝试在监听套接字而不是接受的套接字上设置套接字选项。它会被它们继承。在接受的套接字上设置它可能为时已晚,因为连接握手已经发生,窗口缩放协商等。 – EJP

+0

@EJP:好主意,但我早些时候尝试过没有成功。 –

+0

听起来好像您有一个中间路由器会中断正确的路径MTU发现,因此,毫不奇怪,路径MTU发现不起作用,除非您启用解决方法。究竟是什么神秘?通过向管理它的人抱怨来修复中间路由器。 –

回答

0

FWIW,我发现问题的解决方法/解决方案,将做更多的测试,但很快在这里描述我的发现,以防万一它帮助别人。

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

第二个问题,由getsockopt TCP_MAXSEG返回的错误路径mtu,通过等待TCPACK发送的TCP数据(也使用getsockopt(tcp_info.tcpi_unacked))得到修复。这样,我可以确信,在获取TCP_MAXSEG之前,探测已完成。

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