Home > ブログ > パケット順を入れ替えてのテスト

ブログ

パケット順を入れ替えてのテスト

昨年、あるプロトコル実装のお手伝いをした際、パケットの順序を入れ替えてのテストを行いました。

トランスポート層にTCPを使ったプロトコルなら、TCPレイヤーでパケット順は並べ直されるのでこのようなテストを行うことは通常ありません。 一方、UDPを使ったプロトコルだったり、プロトコルスタック自体のテストを行う場合はこのようなテストが必要になります(*1)。

パケット順の入れ替えが発生する原因

パケット順の入れ替えが発生する原因としてよくあげられるのが「経路の違い」です。送信されたパケットは、すべてが同じ経路を通るとは限らないので、その間に順番が入れ替わるというものです。

他にもルータなどのネットワーク装置の実装により、装置内で入れ替わるケースもあります。

ルータではパケットを高速転送するためにハードウェアで処理することが多いのですが、一部の処理はソフトウェアで処理されます。このケースでパケットの順序が入れ替わることがあります。

例えば、MTU超えのパケットを転送しようとしてIPフラグメントが必要な場合、ソフトウェアで処理されることがあります。この場合、ソフトウェアでフラグメント処理を行っている間に、後から着たMTU内のパケットが先にハードウェア転送されることがあります。

他にも、転送先のARP/NDPエントリがない場合は、パケットをバッファに滞留しますが、ARP/NDPエントリ学習後にハードウェア転送が開始される際、バッファに滞留されていたパケットよりも後から着た中継パケットが先に送信されたりします。

一般に上記のように装置内で入れ替わるのは、経路の違いによるものより再現性があります。

なぜこのようなことをわざわざ書いたかというと、 この手の仕事をしていると、「パケット順の入れ替わりなんてまず発生しないよ」とかかなり軽く考えてテストを蔑ろにする人がいたりするので、パケット順の入れ替わりは環境によっては、わりと発生しているということを説明したかったからです。

パケット順を入れ替えてのテスト

で、パケット順が入れ替わった場合のテストもちゃんとやりましょうという話なのですが、パケットのDropは比較的簡単に実現できるのですが、パケットの順序を狙って入れ替えようとすると結構難しかったりします。

私がこの手のテストを行う場合は、図1のように中間にLinuxノードを挟み、そこでパケットの加工を行うようにしています。

中間ノードでのパケットの加工
図1 中間ノードでのパケットの加工

最初はiptables/nftablesを使ってできないかと思ったのですが、よい方法はないようなので、中間ノード上でTUNデバイスを通して、そこでパケットの入れ替えなどの処理をするようにしています。図1では中間ノードを用意していますが、net namespaceを使って単一ホスト内でテストすることも可能です。

実際にパケットの順序を入れ替えた時のwiresharkでのキャプチャ例を図2,3に示します。 これはDTLSでの例になります。別にプロトコルは何でもよかったのですが、DTLSならパケットにシーケンス番号が入っているので、入れ替わっていることがわかりやすいと思ったので。

No.9のパケット(シーケンス番号2)
図2 No.9のパケット(シーケンス番号2)
No.10のパケット(シーケンス番号1)
図3 No.10のパケット(シーケンス番号1)

No.9のパケットのシーケンス番号が2で(図2)、No.10のパケットのシーケンス番号が1になっており(図3)、順序を入れ替えていることがわかります。

ARP/NDPテスターもそうですが、弊社ではこういった、地味目なところのテストのお手伝いもしています。

(*1) プロトコルスタック自体をテストするということはまずないのですが、ルーターの検収作業のお手伝いでIPフラグメントのテストを行ったことがあります。

投稿日:2023/04/23 14:55

タグ: 作業実績 ネットワーク

Top

アーカイブ

タグ

Server (28) 作業実績 (21) PHP (19) ネットワーク (17) プログラミング (15) OpenSSL (10) C (8) C++ (8) PHP関連更新作業 (8) EC-CUBE (7) Webアプリ (7) laravel (6) 書籍 (5) Nginx (5) Linux (5) AWS (4) Vue.js (4) JavaScript (4) 与太話 (4) Rust (3) Symfony (2) お知らせ (2) Golang (2) OSS (1) MySQL (1) デモ (1) CreateJS (1) Apache (1)