2014-04-15

Multipath TCPについて

Multipath TCPとは、複数の経路を扱うためのTCP拡張である。実は、以前、本の虫: MultiPath TCPのLinuxカーネル実装という記事で、その実装デモを紹介している。

従来のTCPは、IPとの分離ができない。TCPヘッダーの中には、ひとつのIPアドレスとポートがある。経路ごとにIPアドレスが割り振られるので、経路を変えるには、別のTCPコネクションを貼り直さなければならない。

しかし、複数の通信経路を持つという環境は、もはや珍しいものでも何でもなくなっている。たとえば、多くのラップトップにはEthernetとWiFiの二つの経路があるし、スマートフォンにも、WiFiと3G/4Gという複数の経路がある。特にスマートフォンの場合、経路が使えるかどうかが頻繁に切り替わる。

過去に、TCPで複数のIPアドレスを扱う拡張はいくつも出されたが、いずれも、IPアドレスを隠すという点で、非効率的である。

複数の経路を直接扱えれば、パフォーマンス的にも、冗長性的にも、利点がある。

実は、トランスポート層で、複数のIPアドレスを扱うプロトコルは、すでに設計されている。SCTPだ。

SCTPは単に複数のIPアドレスを使えるのみならず、ストリーム単位を混ぜあわせて送信し、受信側でストリーム単位に分解できたり、送信バイト数を通知して、全部受信するまで待機できたりと、従来ならアプリケーション層でやっていたことが、トランスポート層で面倒を見てくれるので、とても便利なのだ。

問題は、SCTPのその他の利点は、とてもニッチな分野でしか需要がない。古い歴史を持つTCPには様々な問題があるとはいえ、既存のTCPからの移行コストを支払ってまで置き換えるほどの利点ではない。

それに、既存のほとんどのルーターが、SCTPパケットを、単に破棄してしまう。卵と鶏の問題と同じで、SCTPの利用者がいないので、ルーターベンダーはSCTPをサポートしない。ルーターがSCTPをサポートしていないので、開発者はSCTPを使えない。

必要とされているのは、既存のTCPパケットとして流せて、既存の機器でも問題なく動く、TCPの拡張だ。それが、Multipath TCPである。

MTCPは、アプリケーションからは、従来のsocketによるTCPと同じように扱える。ただし、アプリケーションが従来のTCPと同じだと信じているものは、実はMTCPによるレイヤーを通した仮想的なもので、本物のTCPコネクションは、MTCPによって管理されている。MTCPは複数の経路をまとめて管理し、アプリケーション側には、従来のTCPのようにみせかける。

MTCPの実装には、TCPオプションを使う。しかし、これは現実的に問題になる。

今日のインターネットは、当初のインターネットとは大きく違う。経路上に、実に多数の、中間箱(middlebox)が存在する。ルーターやスイッチだけではなく、ファイヤーウォールやらNATやらロードバランサーやらDeep Packet Inspectionやらだ。多くの中間箱が、TCPパケットを書き換える。

そもそも、モダンなNICは、効率化のために、勝手にTCPパケットを分割する。この際、TCPヘッダーは、単にコピーされてしまう。そのため、MTCPがTCPヘッダー内で予約して使うデータシーケンス番号が、コピーされてしまう。

MTCPシーケンス番号のコピーは、従来のTCPシーケンス番号の範囲のマッピングにより対処した・・・つもりであった。しかし、これでも問題があった。なんと、多くのルーターが、シーケンス番号を書き換えているのだ。背景には、最初のシーケンス番号をランダムに開始しない脆弱性ある実装に対処するため、ルーター側でシーケンス番号を振り直すということが、広く行われているようなのだ。このため、マッピングを絶対的ではなく、相対的にすることで、対処した。

さらに、active FTPなど、複数のTCPコネクションを貼り、ASCIIでIPアドレスをエンコードするような特定のプロトコルに対し、中身を書き換える(すなわち長さも変わる)などの改変を行うルーターすら存在する。

Linuxカーネルに実装されたMTCPでは、チェックサムを使うことで、データの改変を検知し、従来のTCPにフォールバックする実装になっている。

研究者がインターネット上の中間箱(middlebox)について調査を行ったところ、どうやら今日のインターネットでは、TCPパケットのあらゆる部分は、中間箱により改変される可能性があるということが判明した。これは、将来のTCP拡張を設計する上で考慮に入れなければならないことである。TCPヘッダーの中身のあらゆる箇所は、改変されないという保証がないのだ。

さて、利用例であるが、Wifiと3G/4Gなどの複数の経路を持つスマートフォンやデータセンターが挙げられている。

スマートフォンは、短期間で有効、無効が切り替わる複数の経路でも、TCPコネクションを維持するために使われる。

今日、データセンターでは、複数の経路を使うことは当然になっている。ただしその実装は、複数の経路をロードバランサーなどでまとめて、ラウンドロビンで複数の経路にパケットを割り振り、あたかもひとつのMACアドレス、ひとつのIPアドレスを持つように見せかけている。これは非効率的である。また、通常の経路と、バックアップ用の待機経路を持って、冗長性を確保するという利用方法もある。MTCPならば、複数の経路がそれぞれ異なるMACアドレス、IPアドレスを持てる。直接MTCPが管理するので、パフォーマンス目的でも、冗長性目的でも、効率的に管理できる。

Multipath TCPは、従来のTCPパケットのまま経路上を流せるということと、安全のために従来のTCPへのフォールバックがある、既存のアプリケーションの対応が必要ないという点で、移行しやすい拡張だと言える。

現在、Linuxカーネルで実装されていて、FreeBSDでも実装する計画がある。

さて、流行るだろうか。理想主義者の筆者としては、むしろ抜本的な解決方法として、SCTPのような全く新しいプロトコルが主流になって欲しいのだが。

ドワンゴ広告

この記事は、たまたま、ドワンゴ社内にCOMMUNICATIONS OF THE ACM 04/2014 VOL. 57 NO.04が転がっていたので、興味を引いたMultipath TCPについての論文を読んで、勤務時間中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

8 comments:

Anonymous said...

pythonの件では
下位互換性が大事と考えるのに
TCPでは互換性ぶち壊しを支持するのも
なんかダブルスタンダードな気もしますが…。

Anonymous said...

互換性言い出すと、C++もひどいもんですけどね。
処理系の互換性というとABI互換性とAPI互換性があるわけですが(Pythonのようなスクリプト言語ではこの2つの区別はないですけど)、ABI互換性の影響はエンドユーザーまで波及するのに対し、API互換性は開発者までしか波及しないので、ABI互換性の方が、より重要です。
ところが、C++は、ABI互換性をぶち壊す変更が、これまでたびたびあったわけで…

Anonymous said...

文脈読めない人ってほんとにいるんですね…
MTCPが主流になると、なぜTCPの互換性がぶち壊しになるのかサッパリわかりませんわ

Anonymous said...

↑こいつ自己紹介すぎるだろ

本文をよーく熟読玩味しろ
特に最後の段落を。
分かったら反省しろ。

Anonymous said...

CPUでいうx86の重要性は主に互換性です。その上早いのですからいうことがありません。
アプリケーションを書き直すということはそれなりにコストがかかるのはご存知のとおりです。
困ったら古き道を行けということわざもある通り、互換性を切るのは難しいです。
腐敗させる一手はなにかありますでしょうか。

Takuya ASADA said...

略称は「MTCP」ではなくて「MPTCP」のような気がします。

Takuya ASADA said...

あと、FreeBSDでMPTCPを実装する「計画がある」のではなく、実装されています。
http://caia.swin.edu.au/urp/newtcp/mptcp/

Anonymous said...

最初の2段落目からして内容が根本的に間違っています。TCP/IPの基礎を勉強することをオススメします。