我正在尝试使用IP_MTU_DISCOVER
对udp数据包碎片设置不同的setsockopt()
值的效果,并找到(从man
的{{1}}页面)我需要将其值设置为ip(7)
或IP_PMTUDISC_WANT
以关闭“请勿片段”标记。但是,当我尝试发送数据包时,我得到IP_PMTUDISC_DONT
。
socket.error: [Errno 90] Message too long
谢谢
答案 0 :(得分:2)
让我们首先回顾一下PMTU如何为UDP工作。
ICMP Destination Unreachable
数据包和下一跳MTU。这里需要注意的是,PMTU不会自动发生。在您(应用程序)开始发送实际数据之前,没有内置的探测包可以找出MTU。
因此Linux使用以下标志控制此(对于数据报):
IP_PMTUDISC_WANT
如上所述执行PMTU。如果应用程序发送的数据包对于已知的MTU而言太大,则套接字层将对其进行分段。传出数据包(包括片段)将设置DF位。IP_PMTUDISC_DONT
不要进行PMTU发现。IP_PMTUDISC_DO
PMTU发现。如果应用程序发送的数据包对于已知的MTU来说太大,请向应用程序发送错误。 IP_PMTUDISC_PROBE
设置DF位进行PMTU发现,但忽略当前学习的MTU。因此,如果应用程序发送过大的数据包,它会尝试将其发送出去。这对于不时发送探测以查看PMTU是否没有增加非常有用。现在,通知的一部分是IP_PMTUDISC_DONT
未指定如果数据包实际上大于您当前的MTU(即您的直接链接之一)该怎么办。所以很可能它将这个选择留给实际必须发送数据包的接口。由于未发送DF位,大多数接口实际上应该对数据包进行分段。但是,您使用链接本地接口,该接口通常是具有较少功能的软件接口。您的发行版可能不支持碎片,因此会发送错误。这是有道理的,从我的机器获取此输出:
In [6]: s.getsockopt(socket.IPPROTO_IP, 14) #14 = IP_MTU, just wasn't in my python lib.
Out[6]: 16436
这表明链路本地接口的MTU在网络方面相当庞大,那么为什么要开始支持碎片呢?话虽这么说,在我的系统上,这实际上工作正常。