推荐内核版本
linux-4.19.155
下载地址:https://download.youkuaiyun.com/download/superbfly/14521687
REFERENCE
RFC 8201 - Path MTU Discovery for IPv6
测试流程
TN2:测试设备
TR1:路由(我的理解,可能有偏差)
NUT:被测设备
- TN2发送1400字节长度的Echo Request到NUT
- TN2判断能否收到NUT回复的Echo Reply消息
- TR1发送Packet Too Big消息到NUT(MUT为56)
- TN2再次发送1400字节长度的Echo Request到NUT
- TN2判读能否收到NUT回复的Echo Reply消息(此时消息可能包含分片头)
判断标准
如果在第二步就失败,说明是网络问题。主要功能判断在第五步,这里的通过标准有两种,第一种是回复原始1400字节长度的Echo Replay,第二种是回复带分片头的Echo Replay。我们使用的是第一种方法。
解决方法
直接在NUT的内核中忽略第三步中TR1发送的Packet Too Big消息。
内核代码修改
修改文件:net/ipv6/icmp.c
static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
u8 type, u8 code, int offset, __be32 info)
{
/* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset);
struct net *net = dev_net(skb->dev);
if (type == ICMPV6_PKT_TOOBIG)
{
// 这里加判断,只有Packet Too Big中mtu大于1280时,才更新mtu
if( ntohl(info) >= 1280 )
{
ip6_update_pmtu(skb, net, info, skb->dev->ifindex, 0, sock_net_uid(net, NULL));
}
}
else if (type == NDISC_REDIRECT)
ip6_redirect(skb, net, skb->dev->ifindex, 0,
sock_net_uid(net, NULL));
if (!(type & ICMPV6_INFOMSG_MASK))
if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
ping_err(skb, offset, ntohl(info));
}
通过ntohl(info) >= 1280这个判断,使得mtu小于1280的Packet Too Big不生效,达到回复1400字节内容的目的。