許可をうけて翻訳したものです。Mpps*1過去何年にもわたり、カーネルコミュニティはさまざまなアプローチを使用して、ネットワークパフォーマンスの改善を追求してきました。いくつかの分野で改善が見られますが、アーキテクチャ関連のセキュリティ問題とその対策がほとんどの利点を打ち消してしまい、パケット処理集中型ワークロードに対する純粋なカーネルソリューションはまだバイパスソリューションよりも遅れています。データプレーン開発キット(DPDK)に対して、10倍近い差があります。Pathの名の下に発見しました。8で利用可能で、今すぐダウンロードして実行することができます。このテクノロジを使用すると、カーネルパケット処理にカスタム拡張BPF(eBPF)プログラムをアタッチして新しいネットワーキング機能を実装したり(既存の機能を再実装したり)、ソケットバッファ(SKB)管理やパケット単位のメモリ管理のオーバーヘッドを削減でき、より効率的な一括処理を可能にします。eBPFプログラムは、パケット操作およびパケット転送のためのヘルパー関数にアクセスできるため、新しいカーネル内コードを追加する必要なしに、しかも処理速度を向上しつつ、カーネルの動作を変更および拡張する機会がほぼ無制限に提供されます。Mpps以上を簡単に処理できます。この機会には興奮しますが、未知のものなので怖いですよね?この記事はあなたが最初のXDPプログラムを書くためのガイドです。ゼロから実用的な例を構築し、あなたが高速ネットワークアプリケーションを構築するための準備をします。XDPの概要XDPでは、eBPFプログラムをカーネル内の下位レベルのフックにアタッチすることができます。メソッド)内のネットワークデバイスドライバによって実装されます。プログラムのエントリ関数には引数が1つあります。それは現在のパケットを記述するコンテキストです。プログラムはそのパケットを任意の方法で操作することができますが、eBPFベリファイアによって課される制約に従う必要があります(これについては後でもう少し詳しく説明します)。最後に、そのようなプログラムは、デバイスドライバが処理されたパケットを次にどのように扱うべきかを指定する、制御アクションを返します。上位層の処理に渡すかドロップするかを、所有するデバイスドライバに指示します。eBPFベリファイアはあなたが書くことができるコードにいくつかの制限を課し、プログラムが以下の性質をもっていることを確認する厳密なチェックを実行します。ループを含まない有効なメモリのみにアクセスします(たとえば、パケット境界を超えないようにします)。限られた数のeBPF命令を使用します。4.14カーネルでは制限は128Kです。ベリファイア自体はカーネル内で実行され、eBPFプログラムがeBPFシステムコールを介してロードされたときに実行されます。プログラムが正常にロードされると、任意の数のデバイスのXDPフックにアタッチできます。カーネルソースは、そのような作業を単純化するためのヘルパー関数をもつユーザ空間ライブラリ(libbpf)をバンドルしています。冒険好きな(または上級)ユーザーは、eBPFアセンブラーを使用して直接eBPFプログラムを書くこともできますが、高級言語を使用し、コンパイラーにコードをeBPFに変換させる方がはるかに簡単です。eBPFコミュニティは、そのタスクにLLVMコンパイラとC言語を選択しました。ベリファイアはコンパイルされたコードを検証するので、コンパイラによって実行される最適化は結果に影響を与える可能性があります。定数回のループは、コンパイラによって展開されます。これにより「ループなし」制約を回避できますが、生成されるeBPF命令の数も増えます。入れ子になったループは、128Kの制限に簡単に達する可能性があります。XDPフレーバーすべてのネットワークデバイスドライバがXDPフックを実装しているわけではありません。そのような場合は、コアカーネルによって実装され、特定のネットワークデバイスドライバ機能に関係なく利用可能な、一般的なXDPフックにフォールバックする場合があります。このようなフックはSKB割り当て後にネットワーキングスタックの後半で行われるため、そこでのパフォーマンスはドライバベースのXDPフックよりもはるかに低くなりますが、それでもXDPを試すことができます。4.18以降でXDPフックをサポートするネットワークデバイスドライバは次のとおりです。bnxtthunderi40eixgbemlx4mlx5nfpqedetunvirtio_netこのリストはカーネルのバージョンによって異なる可能性があるので、実行中のカーネルであなた自身のドライバが明示的にサポートされているかチェックする価値があります。その方法については後述します。eBPFプログラムの振る舞いは、プログラムで定義・使用される多数のマップを介してユーザースペースから制御および検査することができます。それらのマップは、libbpfヘルパーを使用してユーザースペースからアクセスや変更も可能です。world"XDPはプログラミング言語ではありませんが、プログラミング言語(eBPF)を使用します。world」プログラムから始めます。eBPFプログラムで出力することはでき、後で説明しますが、もっと単純なXDPの例から始めましょう。eBPFプログラムで、処理された各パケットをカーネルのスタックに渡すだけです。"GPL";上のコードについて詳細を見てみましょう。C言語の構文を使用し、2つの外部ヘッダーを含みます。最初のものは、ほとんどのディストリビューションではkernel-headerパッケージで提供され、XDPプログラムのリターンコード(この例ではXDP_PASS)の定義を含みます。これは、カーネルがパケットをネットワーク処理に渡すことを意味します。他の利用可能な値はXDP_DROP(ドロップする)、XDP_TX(それを受け取ったインタフェースからパケットを送り返す)、XDP_REDIRECT(他のインタフェースからパケットを送る)です。2番目のヘッダは、Linuxカーネルの一部なのですが、ほとんどのディストリビューションでは通常パッケージ化されていません。SEC()マクロの定義が含まれています。後者は、コンパイルされたオブジェクトのフラグメントを指定したELFセクションに配置するために使用されます。そのようなセクションはeBPFローダーよって検出・解釈され、たとえば、プログラムによって定義されたマップを検出する(およびそれらへのユーザースペースアクセスを許可する)ために利用されます。最後の行は、このプログラムに関連するライセンスを正式に指定しています。一部のeBPFヘルパー関数はGPLプログラムでしかアクセスできないので、ベリファイアはこの情報を使用して制限をおこないます。荒削りな点ビルドして実行しましょう。Clangバージョン3.7以降(この記事の執筆にはバージョン6.0が使用されました。make(ここでは4.2.1)が必要です。プログラムはカーネルヘッダを使用するので、アーキテクチャ固有のヘッダ依存関係に対応する必要があります。呼び出すと、次のようになり、期待外れな結果となる場合があります。generated.ここで必要なbpf_helper.hを含む完全なカーネルソースが含まれているディストリビューションのパッケージはほとんどありません。XDPプログラムは完成しましたが、実行するにはカーネル内にロードする必要があります。それほど簡単ではない例では、ロードは通常制御用のユーザ空間プログラムによって行われます。これは一部のマップを介してXDPプログラムを監視/対話します。簡単のために、代わりにiprouteを使います。xdp_dummy.o上記のコードは私達のXDPプログラムを指定されたネットワークデバイスに接続し、デバイスフックを使用しようと試み、そうでなければ一般的なものにフォールバックします。勇敢でサポートされているデバイスドライバを持っている人は、ドライバ固有のフックの使用を強制するようxdpをxdpdrvに置き換えることもできます。Mppsを容易に処理できるため、(イーサネットケーブルを抜いて全てをフィルタしてしまっているのでなければ)これまでにない速度でのパケットフィルタリングを経験できます。意味があること、特定のパケットをドロップしたり、XDPプログラムのアクティビティに関する統計を収集するなどに興味があることでしょう。この連載の次回の記事では、パケットの解析、デバッグ、およびマップの使用法を紹介することによって、それほど簡単ではない例を扱います。各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。