要約

  • 回線事業者の速度制限に見えた転送は、ICMPを通しても回復しなかった。同じソフトウェアでVMを作り直しても障害は再現せず、違いはVMごとの仮想NICにあった。
  • 故障したRTL8139ではTCPオフロードが1500バイトを前提にしていた。経路MTUは1420バイトで、宛先別ルートを1320バイトに固定すると転送が戻った。

分析

Tobias Fiebigの事例で最初に疑われたのは回線事業者だった。サーバー側でICMPを通すよう変更しても、ダウンロードは遅いまま。そこで同じソフトウェアを載せたVMを比べると、失敗する側だけがQEMUのRTL8139を使っていた。遅さの手掛かりは回線の先ではなく、仮想NICの型だった。

大きな転送は、MTUが1500バイト未満の経路を通ると極端に遅くなる。一方、すぐ隣の別VMからは正常に動いた。アクセス側かサーバーのファイアウォールがICMPを落としている、という見立ては自然だ。サーバー側のルールを変更し、「packet too big」の通知を許可してみた。それでも転送速度は変わらなかった。

Fiebigが障害端末で経路を調べると、経路MTUは1420バイトと記録されていた。ホストはすでにローカルの1500バイトより小さい値を知っている。それでもTCPは再送を繰り返す。そこで、宛先に対するより具体的な経路を追加し、MTUを1320バイトに固定した。今度は転送が進んだ。経路検索が示した1420バイトが測定値で、1320バイトは実際に効いた回避策だ。

再現試験は簡単にはいかなかった。Fiebigは同じソフトウェアを入れ、同じパケットを送るVMを作ったが、障害は起きない。差は仮想ハードウェアにあった。故障したゲストはRealtek RTL8139をエミュレートしたNICを使い、試験環境は別のモデルを使っていた。ソフトウェアを揃えただけでは、壊れた条件を再現できていなかった。

調査先はQEMUのnet/hw/8139.cだった。Fiebigによれば、TCPオフロードが固定の1500バイトMTUを使う実装があった。QEMU公式のIssue 1312も、1500未満のリンクにつながるクライアントで低速化し、PMTUDが反映されず、再送が増える現象を記録している。ゲストOS側のMTUを下げると緩和するという。講演では、該当コードが2006年にさかのぼること、2016年にも議論とパッチ提案があったことが紹介された。TCPオフロードを止める方法も挙げられ、報告された環境では古いカードをVirtIOに替えると解消した。

Path MTU Discoveryは、経路の最小MTUに合わせて送信側がサイズを変える仕組みだ。RFC 1191がIPv4の経路MTU探索を説明し、RFC 2923はICMP通知が届かない、または誤って扱われる場合のTCP障害をまとめる。だからファイアウォールは妥当な初動の容疑者だった。変更しても直らないと分かった時点で、次に見るべきはゲストと仮想NICの境界だった。

手順は派手ではない。実際のパケットを取り、経路が学んだMTUを読み、仮想NICの型番とオフロード設定を照合する。公開記録には障害VMのQEMUバージョンと正確なオフロード設定がない。この二つが分かれば、同じ組み合わせがどこまで使われているかを判断できる。

出典

RIPE 93閉幕プレナリーの文字起こし、QEMU Issue 1312、RFC 1191、RFC 2923、TU WienのTobias Fiebig紹介; RIPE 93 セッションページ。