IPv4 での、MTU、および、経路ごとの MTU を調べるプロセス Path MTU Discovery (PMTU Discovery) について理解が甘かったことに気づき、調べました。
type = 3
(Destination Unreachable),
code = 4
(fragmentation needed and DF set)
な
ICMP メッセージを受け取った送信元は、do_pmtu_discovery() を呼びます。
linux-2.6.16.18/net/ipv4/tcp_ipv4.c:386-394
386: case ICMP_DEST_UNREACH: 387: if (code > NR_ICMP_UNREACH) 388: goto out; 389: 390: if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ 391: if (!sock_owned_by_user(sk)) 392: do_pmtu_discovery(sk, iph, info); 393: goto out; 394: }
do_pmtu_discovery() は MTU を ICMP メッセージ中の値
(引数 u32 mtu) に設定します。
linux-2.6.16.18/net/ipv4/tcp_ipv4.c:294
294: dst->ops->update_pmtu(dst, mtu);
設定された値を取得します。
linux-2.6.16.18/net/ipv4/tcp_ipv4.c:302
302: mtu = dst_mtu(dst);
PMTU Discovery を行うべきなら、TCP の MSS
(maximum segment size)
を MTU の値に合わせて設定し、その後、(再送タイマを考慮しない) 再送を行います。
linux-2.6.16.18/net/ipv4/tcp_ipv4.c:304-314
304: if (inet->pmtudisc != IP_PMTUDISC_DONT && 305: inet_csk(sk)->icsk_pmtu_cookie > mtu) { 306: tcp_sync_mss(sk, mtu); 307: 308: /* Resend the TCP packet because it's 309: * clear that the old packet has been 310: * dropped. This is the new "fast" path mtu 311: * discovery. 312: */ 313: tcp_simple_retransmit(sk); 314: } /* else let the usual retransmit timer handle it */