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の詳しい説明

推薦する

webpackコード断片化の実装

目次背景コモンズチャンクプラグイン分割チャンク構成リソースを非同期に読み込む要約する背景高性能なアプ...

Linux CentOS MySQL データベースのインストールと設定のチュートリアル

MySQLデータベースのインストールに関するメモ、みんなで共有a) MySQL ソースインストールパ...

Docker コンテナ データ ボリュームの名前付きマウントと匿名マウントの問題

目次コンテナデータボリュームとはコンテナ データ ボリュームが必要なのはなぜですか?使用データボリュ...

JavaScript ではおそらく switch 文を使う必要はない

目次スイッチも複雑なコードブロックもありませんPythonからのインスピレーション辞書を使用してスイ...

Nginx の場所と proxy_pass パスの設定の問題の概要

目次1. Nginxロケーションの基本設定1.1 Nginx 設定ファイル1.2 Pythonスクリ...

JS 手ぶれ補正機能の実装と使用シナリオ

目次1. 手ぶれ補正機能とは何ですか? 1. なぜ手ぶれ補正機能が必要なのでしょうか? 2. 手ぶれ...

NginxにLuaモジュールを追加する方法

luaをインストールする http://luajit.org/download/LuaJIT-2.0...

WAMPにインストールするとMySQLが起動できるが、再起動後に起動できなくなる問題の解決方法

初めてwampをインストールした後、すべてのサービスが正常に使用できますが、再起動するとwampのア...

RR および RC 分離レベルでのインデックスとロックのテスト スクリプトのサンプル コード

基本概念現在の読み取りとスナップショットの読み取りMVCC では、読み取り操作はスナップショット読み...

MySQL でデータ テーブルを作成し、主キーと外部キーの関係を確立する方法の詳細な説明

序文MySQL テーブルの主キーと外部キーを作成するときは、次の点に注意する必要があります。主キーと...

Pure CSS3はdivの出入りを順番に実現します

この記事は主に、純粋な CSS3 を使用して div が順番に出入りする効果を紹介します。一定の参考...

Dockerfile テキストファイルの使用例の分析

Dockerfile は、イメージをビルドするために使用されるテキスト ファイルです。テキスト コン...

一般的なフロントエンドJavaScriptメソッドのカプセル化

目次1. 値を入力し、そのデータ型を返す** 2. アレイ重複排除3. 文字列の重複排除4. ディー...

dockerプライベート倉庫の構築と利用の詳細説明

1. リポジトリイメージをダウンロードする docker プルレジストリ 2. プライベートウェアハ...

商品クエリ機能を実現するJavaScript

この記事の例では、商品検索機能を実現するためのJavaScriptの具体的なコードを参考までに共有し...