Packetdrillの簡潔なユーザーガイド

Packetdrillの簡潔なユーザーガイド

1. Packetdrillのコンパイルとインストール

  1. ソースコードリンク https://github.com/google/packetdrill.git
  2. ソースコードコンパイル注釈netdev.c
/* オフロードフラグを一般的なイーサネットデバイスと同じように設定します */
静的 void set_device_offload_flags(構造体 local_netdev *netdev)
{
#ifdef Linux の場合
// const u32 オフロード =
// TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN | TUN_F_UFO;
// if (ioctl(netdev->tun_fd, TUNSETOFFLOAD, offload) != 0)
// die_perror("TUNSETOFFLOAD");
#終了
}

./configure && メイク

使い方

./パケットドリルテスト.pkt

test.pkt は、Packetdrill 構文で記述されたテスト スクリプトです。

成功: 出力なし。スクリプトが正しく、すべてが期待どおりであることを示します。

失敗: スクリプトが失敗した場所とその理由を示します。

2. Packetdrillは独自のテストケースを実行する

  1. tcpdump -i 任意の tcp ポート 8080 を開いてパケットをキャプチャし、簡単に分析できるようにします。
  2. ここでは高速再送信をテストしており、テスト環境はcentos7.2です。
  3. 簡単な説明: < は入力を示し、packetdrill は実際のデータ パケットを構築します。 >プロトコル スタックが応答することが予想されるパケットを示します。 (このパケットは packetdrill によって構築されるのではなく、プロトコル スタックによって送信されます。)
// 4 つのパケットが未処理で、受信側が SACK を送信している状態で高速再送信をテストします。
// このバリアントでは、受信側は SACK をサポートします。
// 接続を確立します。
0 ソケット(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 バインド(3, ..., ...) = 0
+0 聞く(3, 1) = 0
//3ウェイハンドシェイク+0 < S 0:0(0) win 32792 <mss 1000、sackOK、nop、nop、nop、wscale 7>
+0 > S. 0:0(0) ack 1 <...>
+.1 < . 1:1(0) ack 1 勝利 257
+0 受け入れる(3, ..., ...) = 4
// システム コール、プロトコル スタックに 100 バイトを送信させます // 1 つのデータ セグメントを送信して ACK を取得します。そのため、cwnd は 4 になります。
+0 書き込み(4, ..., 1000) = 1000
//プロトコルスタックはpsh、ackを送信すると予想されますが、実際にはack1を送信します
//+0 > P. 1:1001(1000) 確認 2
//プロトコルスタックにackを挿入する
+.1 < . 1:1(0) ack 1001 勝利 257
// 4 つのデータ セグメントを書き込みます。
//システムコール、プロトコルスタックに4000バイト+0を送信させる write(4, ..., 4000) = 4000
//プロトコル スタックは psh、ack を送信すると予想されますが、実際には seq 1001:2001、ack 1、seq 2001:3001、ack 1、seq 3001:4001、ack 1、[P.]、seq 4001:5001、ack 1 が送信されます。
//+0 > P. 1001:5001(4000) 確認1
// 3 つの SACK を取得します。
// プロトコルスタックに 3 つの ACK を連続して送信します
+.1 < . 1:1(0) ack 1001 win 257 <sack 2001:3001,nop,nop>
+0 < . 1:1(0) ack 1001 win 257 <sack 2001:4001,nop,nop>
+0 < . 1:1(0) ack 1001 win 257 <sack 2001:5001,nop,nop>
// 重複した ACK を 3 つ受信したので、高速再送信を行います。
//プロトコルスタックは高速再送信シーケンス 1001:2001、ack 1 を発行することが期待されます
//+0 > . 1001:2001(1000) 確認 1
// 受信側はすべてのデータを ACK します。
//プロトコル スタックに ACK を送信し、すべてのメッセージの ACK に応答します。
+.1 < . 1:1(0) ack 6001 勝利 257
4. fr-4pkt-sack-linux.pkt を次のように変更します。
+0 > P. 1:1001(1000) 確認応答 2  +0 > P. 1:1001(1000) 確認応答 1
//+0 > P. 1001:5001(4000) 確認応答 1  
+0 > . 1001:2001(1000) 確認 1
+0 > . 2001:3001(1000) ack 1
+0 > . 3001:4001(1000) 確認 1
+0 > P.4001:5001(1000) 確認1

[注: packetdrill が提供するテスト ケースを実行する際にエラーが発生する場合、通常はプロトコル スタックが送信したパケットが期待されるパケットと一致していないことが原因です。まず、期待されるパケットよりも大きい部分を排除してからテスト ケースを実行し、パケットをキャプチャして期待される結果を分析してください。通常、3ウェイハンドシェイクmssの制限によるものです。

  1. 実行中: ../../../packetdrill fr-4pkt-sack-linux.pkt、エラーなし。
  2. パケットをキャプチャすると、次の結果が確認できます。ACK が 3 回繰り返されると、高速再送信が実装されます。期待された効果を達成します。
// 3 回の繰り返し ack 1001 を実装するためにパケットを自分で構築します。
07:57:36.469280 IP 192.0.2.1.36840 > TENCENT64.site.webcache: フラグ [.]、ack 1001、win 257、オプション [sack 1 {2001:3001}、nop、nop]、長さ 0
07:57:36.469836 IP 192.0.2.1.36840 > TENCENT64.site.webcache: フラグ [.]、ack 1001、win 257、オプション [sack 1 {2001:4001}、nop、nop]、長さ 0
07:57:36.470349 IP 192.0.2.1.36840 > TENCENT64.site.webcache: フラグ [.]、ack 1001、win 257、オプション [sack 1 {2001:5001}、nop、nop]、長さ 0
// プロトコル スタックは高速再送信を開始します。シーケンス 1001:2001、ack 1,1000
07:57:36.470376 IP TENCENT64.site.webcache > 192.0.2.1.36840: フラグ [.]、シーケンス 1001:2001、ack 1、win 229、長さ 1000

3. Packetdrillは独自のテストケースの説明を説明しています

ここでは主にpacketdrillの基本的な構文について説明します。

スクリプトには、データ パケット、システム コール、シェル コマンド、Python ステートメントの 4 種類のステートメントを含めることができます。
各ステートメントは、実行された時刻を示すタイムスタンプで始まる必要があります。

  • パケット

データパケットは入力データパケットと出力データパケットに分かれており、フォーマットはtcpdumpに似ています。
TCP、UDP、ICMP、およびほとんどの TCP オプションをサポートします。

入力データ パケット (< は入力を意味します): Packetdrill は実際のデータ パケットを構築し、それをプロトコル スタックに挿入します。

例:

0.100 < S 0:0(0) 勝利 32792 <mss 1000、nop、nop、sackOK、nop、wscale 7>
0.250 < [1:1461(1460)] icmp 到達不能 frag_needed mtu 1200

出力データ パケット (> は出力を示します): packetdrill は、プロトコル スタックが実際にそのようなパケットを送信するかどうかを確認します。

+0 > udp (1472)
  • システムコール

システムコールの形式は strace に似ています。
各システムコールについて、packetdrill は指定された時間にそれを実行し、戻り値が期待どおりであるかどうかを確認します。システムコールは主にシーン構築や非テスト終了時のデータ送受信に使用されます。

一般的なシステムコールの例:
システムコール

connect(3, ..., ...) = -1 EINPROGRESS (操作が進行中) //クライアントがサーバーに接続 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 //socketoptを取得
fcntl(3, F_SETFL, O_RDWR) = 0 //Fcntl 設定 ioctl(4, SIOCINQ, [1000]) = 0 //Ioctl 設定 read(3, ..., 1024) = 785 //データ読み取り write(3, ..., 57) = 57 //データ書き込み close(3) = 0 //接続を閉じる socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 //Tcp ソケット
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 //アドレス再利用を設定 bind(3, ..., ...) = 0 //ポートをバインド listen(3, 1) = 0 //ポートをリッスン accept(3, ..., ...) = 4 //接続を受け入れる
  • シェルスクリプトの使用

一般的な使用法としては、シェル スクリプトを使用してカーネル パラメータを設定したり、シェル コマンドを呼び出して TCP 統計を収集したりすることが挙げられます。設定

例:

+0 `sysctl -q net.ipv4.tcp_timestamps=0`
+0 `ss -4 -n 状態 SYN-RECV | grep 192.168.0.1:8080 > /dev/null`
  • Pythonスクリプトの使用

一般的な使用法は、Python の assert を使用して、tcp_info の情報が期待どおりであるかどうかをアサートすることです。

例:

0.310%
tcpi_reordering == 3 をアサートする
tcpi_unacked == 10 をアサートする
tcpi_sacked == 6 をアサートする
tcpi_ca_state == TCP_CA_Recovery をアサートする
}%
  • タイムスタンプ

各ステートメントは、実行された時刻、またはイベントの発生が予想される時刻を示すタイムスタンプで始まる必要があります。タイミングの問題によりテストケースが失敗する可能性があります。

タイムスタンプにはさまざまな形式を使用できます。

絶対値: 0.75
相対: +0.2
ワイルドカード(いつでも):*
範囲(絶対時間間隔):0.750〜0.900
相対範囲: +0.1~+0.2
緩い(許容誤差値): --tolerance_usecs=800
ブロッキング(ブロッキング時間間隔):0.750...0.900

対応するイベントが指定されたタイムスタンプで発生しない場合は、エラーが報告され、イベントの実際の発生時刻が通知されます。

+1.0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 6>

TCP は 1 秒後に SYNACK パケットを送信することが予想されます。

実際の使用では、一般的に –tolerance_usecs=405000 が指定され、これは 4 ミリ秒の時間誤差が許容されることを意味します。

4. Packetdrillが基本シナリオ構築テストを実装

シーンのシーン構造は、クライアント シーンまたはサーバー シーンのいずれかです。特定のパッケージを構築する方法の詳細については、packetdrill に付属するテスト ケースを参照してください。

1. サーバーシナリオ

サーバー側のシナリオを構築します。データ パケットの入力側はクライアントです。パケットの出力先はサーバーとして機能するシステムコールです。

// 接続を確立します。
0.000 ソケット(..., SOCK_STREAM, IPPROTO_TCP) = 3
0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
0.000 バインド(3, ..., ...) = 0
0.000 聞く(3, 1) = 0
0.000...0.200 accept(3, ..., ...) = 4
0.100 < S 0:0(0) 勝利 32792 <mss 1000,nop,wscale 7>
0.100 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 6>
0.200 < . 1:1(0) ack 1 勝利 257
// サーバーはシステム コールを呼び出し、2 つのパケットを送信することを期待します。
0.300 書き込み(4, ..., 2000) = 2000
//0.300 > P. 1:2001(2000) ack 1
0.300 > . 1:1001(1000) ack 1
0.300 > P. 1001:2001(1000) ack 1

1. クライアントシーンの構築

サーバー側のシナリオを構築します。データ パケットの入力側はサーバー側です。パケット出力側はクライアントとして機能するシステムコールです。

// ソケットを作成し、非ブロッキングに設定します。
0.000 ソケット(..., SOCK_STREAM, IPPROTO_TCP) = 3
0.000 fcntl(3, F_GETFL) = 0x2 (フラグ O_RDWR)
0.000 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
// 接続を確立し、エラーがなかったことを確認します。
0.100 connect(3, ..., ...) = -1 EINPROGRESS (操作が進行中です)
0.100 > S 0:0(0) <mss 1460、sackOK、TS値100 ecr 0、nop、wscale 6>
0.200 < S. 0:0(0) ack 1 win 5792 <mss 1460、sackOK、TS val 700 ecr 100、nop、wscale 7>
0.200 > . 1:1(0) ack 1 <nop,nop,TS 値 200 ecr 700>
// クライアントは、http リクエストを行うことを期待してシステム コールを呼び出します。
// HTTP リクエストを送信します。
0.200 書き込み(3, ..., 57) = 57
0.200 > P. 1:58(57) ack 1 <nop,nop,TS val 200 ecr 700>
0.300 < . 1:1(0) ack 58 win 92 <nop,nop,TS val 800 ecr 200>

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。これについてもっと知りたい場合は、次のリンクをご覧ください。

以下もご興味があるかもしれません:
  • Java URL カスタム プライベート ネットワーク プロトコル
  • SQL Server 2008 ネットワーク プロトコルの詳細な理解
  • Getmac は、コンピューター内のすべてのネットワーク カードのメディア アクセス制御 (MAC) アドレスと、各アドレスのネットワーク プロトコルのリストを返します。
  • Winsockfix ネットワーク プロトコル修復ツール
  • TCPプロトコルの詳しい説明_Powernode Java Academy
  • Python3 は TCP プロトコルのシンプルなサーバーとクライアントの例を実装します (共有)
  • TCP プロトコルに基づくサーバーとクライアントの通信プログラミングに関する C# の基本チュートリアル
  • C言語を使用してTCPプロトコルに基づくソケット通信プログラムを作成する
  • Androidプログラミングでは、HTTPプロトコルとTCPプロトコルを使用してファイルをアップロードします。
  • TCP プロトコルに基づく Java ソケット プログラミングの例
  • .Net WInform 開発ノート (II) Winform プログラムの動作構造図と Winform における TCP プロトコルの適用

<<:  CentOS7 64ビットインストールmysqlグラフィックチュートリアル

>>:  JavaScript Reduceの詳しい説明

推薦する

jQuery+swiper コンポーネントはタイムラインのスライド年タブ切り替え効果を実現します

結果: 実装コード: スワイパーコンポーネントと一緒に使用する必要がありますSwiper 基本デモア...

js でオブジェクトを作成するさまざまな方法とその長所と短所のまとめ

目次初期作成方法ファクトリーパターンコンストラクターパターンコンストラクタパターンの最適化プロトタイ...

jsイベント委譲の詳細な説明

1. 各関数はオブジェクトであり、メモリを占有します。メモリ内のオブジェクトが増えるほど、パフォーマ...

Windows 10 Home EditionにDockerをインストールする方法を教えます

Redisの本やSpring Cloud Alibabaの本を執筆した際に、一部の分散コンポーネント...

Dockerカスタムブリッジdocker0とdockerのコマンド操作の開始、終了、再起動

質問会社がサーバーを移行した後、デフォルトで作成された docker0 ブリッジが会社の外部ネットワ...

CentOS6で定期的にjarプログラムを実行するスクリプトをcrontabで実行する

1. 簡単なJavaプログラムを書く パブリッククラステストシェル{ パブリック静的voidメイン(...

VUE+SpringBootはページング機能を実装します

この記事では主に、Vue + SpringBoot でページ分割されたリストデータを実装する方法を紹...

Mysql systemctl start mysqld によって報告されるエラーの解決策

エラーメッセージ:制御プロセスがエラー コードで終了したため、mysqld.service のジョブ...

フレックスレイアウトは、上下固定、中間スライドのレイアウトモードを実現します。

この記事では、主に、上下固定と中スライドレイアウトを実現するためのフレックスレイアウトのレイアウト方...

タグのhref属性とonclickイベントの使用例

a タグは主にページ ジャンプを実装するために使用され、これは href 属性または onclick...

Linuxのlocateコマンドの使い方

01. コマンドの概要実際には、locate コマンドは find -name の別の書き方ですが、...

SQL ステートメント実行の詳細な説明 (MySQL アーキテクチャの概要 -> クエリ実行プロセス -> SQL 解析順序)

序文:私はずっと、SQL 文がどのように、どのような順序で実行されるのかを知りたいと思っていました。...

Linuxで権限が拒否された場合の解決策の詳細な説明

許可が拒否されました:その理由は、ファイルの読み取り、書き込み、作成、削除などの権限がないためです。...

Centos7 に yum を使用して MySQL をインストールし、リモート接続を実現する方法

Centos7はyumを使用してMySQLをインストールし、リモート接続を実現する方法です。MySQ...

MySQL実行計画を学ぶ

目次1. 実施計画の概要2. 実行計画の実践id:選択タイプ:テーブル:タイプ:可能なキー:鍵:キー...