Path MTU Discovery

首藤 一幸

2006年 7月 29日


Back to


Path MTU Discovery の方法

IPv4 での、MTU、および、経路ごとの MTU を調べるプロセス Path MTU Discovery (PMTU Discovery) について理解が甘かったことに気づき、調べました。

Linux (2.6.16.18) / IPv4 / TCP での実装

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 */