I. 背景紹介Linuxカーネルネットワーク開発において、ネットワークパケットロスは一般的な課題です。従来のネットワークキャプチャツール(tcpdumpなど)は開発者が問題を特定するのに役立ちますが、効率が悪く、ネットワークの深層部の問題を正確に特定する能力には限界があります。eBPF技術の急速な発展に伴い、より高度な問題追跡機能が登場しています。ByteDanceのSTEチームは、この技術をベースに次世代カーネルネットワークキャプチャツール「 netcap (net capture、社内では当初xcapと呼ばれていました) 」を開発し、正式にオープンソース化しました。GitHubアドレス:https://github.com/bytedance/netcap。 tcpdumpはカーネルネットワークプロトコルスタック内のパケット送受信準備の固定ポイントのみを操作しますが、netcapはカーネルネットワークプロトコルスタックのほぼ全体をトレースできます(skbをパラメータとして機能します)。ByteDanceのSTEチームは、tcpdump構文をフィルタリング条件として使用し、skb(ソケットバッファ)をコンテキストとして、カーネルネットワークプロトコルスタック内のパケット全体の完全なトレースを容易に把握できるようにすることで、開発者がカーネルネットワークのパケットロス問題の特定効率を大幅に向上させます。 II. 使用例例1 :IPアドレス10.227.0.45からのICMPパケットがカーネルの想定される関数呼び出しポイントに到達したかどうかを確認します。これを行う利点は、ネットワークの問題を特定してトラブルシューティングする際に、疑わしい範囲を容易に絞り込み、効率を向上させることができることです。 -f に続くパラメーターは、kprobe または tracepoint の特定の機能 (デフォルトは kprobe) であり、この機能内のどのパラメーター skb であるか (1 から始まる) を netcap に伝える必要があります。この例では、これが最初のパラメーターです。
例 2: TCP ポート 9000 のカーネル内でパケット損失の場所を確認します。 -f に続くパラメータは、kprobe または tracepoint の特定の機能です。tracepoint の場合、skb がどのパラメータであるかを渡す必要はありません。 -S オプションは、この呼び出しのスタックも出力することを示します。この例では、スタックにはパケットロスが発生した場所が表示されます。 たとえば、次の図に示すように、着信 TCP 9000 パケットをドロップするようにマシン上で iptables ルールを構成します。 次に、netcap のコマンドを使用してパケット損失の状況を観察します。 その他のコマンドライン パラメータの詳細については、オープン ソース コードの README を読むか、コマンド netcap help skb を使用してください。 III. 設計と実装メインフレームワークNetcap は kprobe/tracepoint を使用して関数をフックし、関数パラメータを通じて skb および sock キー構造を取得し、ネットワーク パケット データを取得してから、BPF マップを介してデータをユーザー空間に送信します。 実施原則netcapの基本的な動作原理は次のとおりです。eBPFプログラムでは、tcpdump構文でフィルタリングされたパケットを識別するためのパケットフィルタリングが実行されます。このパケットはnetcapアプリケーションに渡され、netcapアプリケーションはtcpdumpに送信して表示するか、直接pcapファイルに出力します。下の図をご覧ください。 1. tcpdump構文に従ってフィルタリングする方法 tcpdumpのフィルタリング構文はcBPFに基づいており、オープンソースライブラリ(https://github.com/cloudflare/cbpfc)を使用しています。このライブラリはtcpdumpのフィルタリング構文をC関数に変換し、netcapのeBPFプログラムに組み込むことができます。C関数への変換の基本原理は次のとおりです。まず、libpcapライブラリを使用してtcpdumpのフィルタリング構文をcBPFの命令コードに変換し、次にこの命令コードをC言語の関数に変換します。下の図をご覧ください。 2. tcpdump を使用してデータ パケットの内容を表示するにはどうすればよいですか? netcap プログラムが起動すると、tcpdump プログラムも起動します。tcpdump は標準入力で pcap 形式の入力ストリームを受け取り、解析されたフォーマットを標準出力に出力します。出力には様々なパラメータ(例:-e は MAC アドレスを表示します)が用いられます。以下の図をご覧ください。 3. データ パケットの内容を見つけるにはどうすればよいでしょうか? カーネルでは、データパケットはskbを用いて記述されます。skbに指定された様々なヘッダーの位置を見つけることで、データパケット全体を特定できます。skbの一般的な構造は次のとおりです。 4. 送信方向のデータ パケットが不完全な場合にデータ パケットをフィルター処理するにはどうすればよいですか? __ip_finish_output 関数などでデータパケットを送信する際、ETH ヘッダー、IP ヘッダー、TCP ヘッダーが完全に埋められていない場合があります。では、どうすれば完全なパケットを取得できるのでしょうか? Netcapはskbのsock構造に基づいてデータパケットを推測し、再構築しようとします。ただし、キャプチャされたパケット内の重要でない情報(IPヘッダーのidフィールドなど)は、実際のデータと異なる場合があります。skbがsock構造からパケットの内容を推測する一般的なロジックは、次の図に示されています。 IV. その他の用途と拡張マルチトレースポイントサマリー分析Netcapは、データパケットが複数のポイントを通過するのにかかる時間を分析し、その出力を要約してパフォーマンスを分析できます。例えば、次のコマンドを使用します。 出力は次のように確認できます。トレースポイントに到達するまでの時間に基づいて、データパケットのパフォーマンスが低下している場所や、レイテンシが発生している可能性のある場所を分析できます。 拡張機能ユーザーは独自のフィルタリングと出力関数を定義できます。以下に例を示します。 拡張フィルター ファイル skb_user_filter.c は次のとおりです。 この拡張機能の戻り値が0の場合、tcpdump構文のフィルタリング後に、ユーザー定義のフィルタが再度実行されることを意味します。例えば、数行のスクリプトを記述し、skb->markに従ってフィルタリングするだけで簡単に実現できます。 拡張出力ファイル skb_user_action.c は次のとおりです。 `struct xcap_user_extend` はユーザー定義構造体です。必要な出力情報はこの構造体内で定義され、値が割り当てられます。この構造体でサポートされる型は以下のとおりです(注:ポインタと配列はサポートされていません):`int8_t`、`uint8_t`、`char`、`int16_t`、`uint16_t`、`int`、`uint32_t`、`int64_t`、`uint64_t`。 これにより、下の画像に示すように、追加情報を出力できるようになります。 V. 今後の展望開発者の日常業務において、ネットワークパケットキャプチャツールは、ネットワークエンジニアやテストエンジニアなどにとって不可欠なスキルとなっています。ByteDanceのSTEチームは、カーネルネットワークのパケットロス問題の特定効率向上に貢献できるよう、netcapネットワークパケットキャプチャツールをオープンソース化しました。開発者の皆様のご参加とプルリクエストの投稿を心よりお待ちしております。このオープンソースプロジェクトの開発を共同で推進してまいります。今後、以下の分野においても最適化を進めていく予定ですので、ご期待ください。
|