味噌汁を飲みます

そんなに深く考えて書いていない twitter: siberiy4

LinuxのSCTPのDPLPMTUDの探索は本当に線形探索なのか?

LinuxのSCTPのDPLPMTUDの探索は本当に線形探索なのか?

この記事は、 404 Advent Calendar 2022の16日目の記事です。

DPLPMTUとは

MTUはあるホストが受け取り転送できるIPパケットの最大サイズをMTUという。 NWのインターフェースごとに設定でき、デフォルトは1500だがたいていの機器は9000まで設定可能である。
また、送信元から送信先までのMTUの最小値をPath MTUという。

ある機器に到達したパケットのサイズがMTUを超えていると、フラグメンテーション(パケットの分割)やパケットのドロップを行う。
IPv6はデフォルトでフラグメンテーション不可であるし、UDPフラグメンテーション不可だ。
そのため、Path MTUを調べてそのサイズ以上のパケットを送らないようにする必要がある。

万が一MTUより大きいパケットが来た場合、そのホストはパケットをドロップする際にICMPのエラーでドロップしたパケットの送信元にドロップしたホストのMTUを通知します。この仕組みをPath MTU Discoveryといいます。
しかし、世界では何らかの理由でICMPを拒否するネットワークがあるため送信元までICMPのエラーメッセージが到達しない可能性があります。これをICMPブラックホールといいます。

ICMPブラックホールを避けてPath MTUを計測するために、実際にその大きさのTCPパケットを送信先に投げつけて探索していこうという、Packetization Layer Path MTU Discovery (PLPMTUD) という仕様である。
これのUDPバージョンをDatagram Packetization Layer Path MTU Discovery (DPLPMTUD) という。

本題

昨日、翻訳にかけたブログ 元記事 翻訳かけたやつ

にて、DPLPMTUDの探索アルゴリズムは、失敗するまで32ずつ上昇させて失敗後は4ずつ上昇させて、それでも失敗したらPath MTUを見つけたとして探索を終わると記載がある。

GitHubリポジトリを覗いたところ、ここが探索時の暫定のPath MTUを上昇させる部分である。
329行目の

t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_BIG_STEP,
                           SCTP_MAX_PLPMTU);

にて SCTP_MAX_PLPMTU(9000byte)より小さい場合は32byteずつ上昇させている。 t->pl.probe_highに値が入らない限り上のしょりが行われる。
では、逆に値が入る条件というのは、ここである。
/* Normal probe failure. */とあるのでprobeに失敗した(投げたPath MTU確認用パケットの応答が送信先から3回なかった)ときのようである。
ここで値が入っているので、SCTP_PL_MIN_STEP(4byte)ずつ増えるこの処理はprobe失敗後の処理であることが分かる。

334行目から342行目の条件分岐は、SCTP_PL_MIN_STEP(4byte)追加後に失敗したprobeのパケットサイズ以上であれば探索のしようがないので探索を終了している。

これらから、RedHatのDeveloperブログにあった

DPLPMTUDの探索アルゴリズムは、失敗するまで32ずつ上昇させて失敗後は4ずつ上昇させて、それでも失敗したらPath MTUを見つけたとして探索を終わる という仕様は本当だった。 という結論にいたりました。

以上、ありがとうございました。