第42章 RHEL 9 の eBPF ネットワーク機能について
eBPF (extended Berkeley Packet Filter) は、カーネル領域でのコード実行を可能にするカーネル内の仮想マシンです。このコードは、限られた一連の関数にのみアクセスできる制限付きサンドボックス環境で実行されます。
ネットワークでは、eBPF を使用してカーネルパケット処理を補完したり、置き換えることができます。使用するフックに応じて、eBPF プログラムには以下のような記述があります。
- パケットデータおよびメタデータへの読み取りおよび書き込みアクセス
- ソケットとルートを検索できる
- ソケットオプションを設定できる
- パケットをリダイレクト可能
42.1. RHEL 9 におけるネットワーク eBPF 機能の概要 リンクのコピーリンクがクリップボードにコピーされました!
Extended Berkeley Packet Filter (eBPF) を使用すると、開発者は Linux カーネルでサンドボックス化されたプログラムを実行できます。ネットワークの場合、eBPF プログラムはフックに接続してトラフィックを検査、変更、フィルタリングします。
eBPF (extended Berkeley Packet Filter) ネットワークプログラムは、RHEL の以下のフックに割り当てることができます。
- eXpress Data Path (XDP): カーネルネットワークスタックが受信したパケットを処理する前に、このパケットへの早期アクセスを提供します。
-
tceBPF 分類子 (direct-action フラグ): ingress および egress で強力なパケット処理を提供します。プログラムは、qdisc階層内の direct-action フラグを使用して eBPF 分類子として割り当てることも、リンクベースのtcxAPI を使用して割り当てることもできます。 - Control Groups version 2 (cgroup v2): コントロールグループ内のプログラムが実行するソケットベースの操作のフィルタリングおよび上書きを有効にします。
- ソケットフィルタリング: ソケットから受信したパケットのフィルタリングを有効にします。この機能は、従来の Berkeley Packet Filter (cBPF) でも利用できますが、eBPF プログラムに対応するために拡張されました。
- ストリームパーサー : 個別のメッセージへのストリームの分散、フィルタリング、ソケットへのリダイレクトを有効にします。
-
SO_REUSEPORTソケットの選択:reuseportソケットグループから受信したソケットをプログラム可能な選択を提供します。 - flow dissector: 特定の状況でカーネルがパケットヘッダーを解析する方法をオーバーライドします。
- TCP 輻輳制御コールバック: カスタム TCP 輻輳制御アルゴリズムの実装を有効にします。
カプセル化によるルート: カスタムのトンネルカプセル化の作成を有効にします。
- XDP
BPF_PROG_TYPE_XDPタイプのプログラムはネットワークインターフェイスに割り当てることができます。次にカーネルは、カーネルネットワークスタックが処理を開始する前に受信したパケットでプログラムを実行します。これにより、高速パケットドロップなど、特定の状況で高速なパケット転送が可能になり、負荷分散シナリオにおいて DDoS (Distributed Denial of Service) 攻撃や高速パケットリダイレクトを防ぐことができます。さまざまな形式のパケット監視やサンプリングに XDP を使用することもできます。カーネルは、XDP プログラムはパケットを変更し、カーネルネットワークスタックへのさらなる処理を可能にします。
以下の XDP モードを使用できます。
- ネイティブ (ドライバー) XDP: カーネルは、パケット受信時に最速の可能点からプログラムを実行します。この時点で、カーネルはパケットを解析しなかったため、カーネルが提供するメタデータは利用できません。このモードでは、ネットワークインターフェイスドライバーが XDP をサポートしている必要がありますが、すべてのドライバーがこのネイティブモードをサポートするわけではありません。
- 汎用 XDP: カーネルネットワークスタックは、処理の初期段階で XDP プログラムを実行します。この時点で、カーネルデータ構造が割り当てられ、パケットを事前に処理しています。パケットをドロップまたはリダイレクトする必要がある場合は、ネイティブモードと比較して大きなオーバーヘッドが必要になります。ただし、汎用モードはネットワークインターフェイスドライバーのサポートを必要とせず、すべてのネットワークインターフェイスで機能します。
- オフロードされた XDP: カーネルは、ホストの CPU 上ではなく、ネットワークインターフェイスで XDP プログラムを実行します。これには特定のハードウェアが必要で、特定の eBPF 機能のみがこのモードで使用できることに注意してください。
RHEL で、
libxdpライブラリーを使用してすべての XDP プログラムを読み込みます。このライブラリーは、XDP のシステム制御を可能にします。注記現在、XDP プログラムにはシステム設定に制限があります。たとえば、受信側インターフェイスで特定のハードウェアオフロード機能を無効にする必要があります。また、ネイティブモードをサポートするすべてのドライバーで利用可能なわけではありません。
RHEL 9 では、
libxdpライブラリーを使用してプログラムをカーネルにロードする場合にのみ、Red Hat は XDP 機能をサポートします。- AF_XDP
-
指定した
AF_XDPソケットにパケットをフィルターしてリダイレクトする XDP プログラムを使用すると、AF_XDPプロトコルファミリーから 1 つ以上のソケットを使用して、カーネルからユーザー空間にパケットを速やかにコピーできます。 - トラフィック制御
Traffic Control (
tc) サブシステムは、以下のタイプの eBPF プログラムを提供します。-
BPF_PROG_TYPE_SCHED_CLS -
BPF_PROG_TYPE_SCHED_ACT
これらのタイプを使用すると、カスタム
tc分類子とtcアクションを eBPF に記述できます。これは、tcエコシステムの一部とともに、強力なパケット処理機能を提供します。また、複数のコンテナーネットワークオーケストレーションソリューションの中核となります。多くの場合、direct-action フラグと同様に、eBPF 分類子は、同じ eBPF プログラムから直接アクションを実行できます。
clsactQueueing Discipline (qdisc) は、Ingress 側でこれを有効にするように設計されています。flow dissector の eBPF プログラムは、
flowerなどのその他のqdiscsやtc分類子の操作に影響を与える可能性があることに注意してください。リンクベースの
tcxAPI は、qdiscAPI とともに提供されます。これにより、アプリケーションが BPF プログラムの所有権を維持し、BPF プログラムが誤って削除されるのを防ぐことができます。また、tcxAPI にはマルチプログラムサポートがあり、複数のアプリケーションがtcレイヤーに BPF プログラムを並行して接続できます。-
- ソケットフィルター
複数のユーティリティーは、ソケットで受信されるパケットのフィルタリングに、従来の Berkeley Packet Filter (cBPF) を使用または使用しています。たとえば、
tcpdumpユーティリティーを使用すると、ユーザーは、どのtcpdumpを cBPF コードに変換するか、式を指定できます。cBPF の代替として、カーネルは、同じ目的で
BPF_PROG_TYPE_SOCKET_FILTERタイプの eBPF プログラムを許可します。- コントロールグループ
RHEL では、cgroup に割り当てられる eBPF プログラムを複数使用できます。カーネルは、指定の cgroup のプログラムが操作を実行する際に、これらのプログラムを実行します。cgroups バージョン 2 のみを使用できます。
RHEL では、以下のネットワーク関連の cgroup eBPF プログラムが利用できます。
-
BPF_PROG_TYPE_SOCK_OPS- カーネルは、さまざまな TCP イベントでこのプログラムーを呼び出します。プログラムは、カスタム TCP ヘッダーオプションなどを含め、カーネル TCP スタックの動作を調整できます。 -
BPF_PROG_TYPE_CGROUP_SOCK_ADDR: カーネルは、connect、bind、sendto、recvmsg、getpeername、およびgetsocknameの操作中にこのプログラムを呼び出します。このプログラムは、IP アドレスとポートを変更できます。これは、ソケットベースのネットワークアドレス変換 (NAT) を eBPF に実装する場合に便利です。 -
BPF_PROG_TYPE_CGROUP_SOCKOPT: カーネルは、setsockoptおよびgetsockopt操作時にこのプログラムを呼び出して、オプションの変更を可能にします。 -
BPF_PROG_TYPE_CGROUP_SOCK: カーネルは、ソケットの作成時、ソケットの開放時、アドレスのバインド時にこのプログラムを呼び出します。これらのプログラムを使用して操作を許可または拒否するか、統計のソケット作成の検査のみを行います。 -
BPF_PROG_TYPE_CGROUP_SKB: このプログラムは ingress および egress の個別のパケットをフィルターし、パケットを受信または拒否できます。
-
- ストリームパーサー
ストリームパーサーは、特別な eBPF マップに追加されるソケットのグループで動作します。次に、eBPF プログラムは、カーネルがこれらのソケットで受信または送信するパケットを処理します。
RHEL では、以下のストリームパーサー eBPF プログラムを利用できます。
-
BPF_PROG_TYPE_SK_SKB: eBPF プログラムは、ソケットで受信したパケットを個別のメッセージに解析し、それらのメッセージを破棄するか、受け入れるか、別のソケットに送信するかをカーネルに指示します。 -
BPF_PROG_TYPE_SK_MSG: このプログラムは egress メッセージをフィルタリングします。eBPF プログラムはパケットを解析し、承認または拒否します。
-
- SO_REUSEPORT ソケットの選択
-
このソケットオプションを使用することで、複数のソケットを同じ IP アドレスとポートにバインドできます。eBPF がない場合、カーネルは接続ハッシュに基づいて受信ソケットを選択します。
BPF_PROG_TYPE_SK_REUSEPORTプログラムを使用すると、受信ソケットの選択が完全にプログラム可能になります。 - Flow dissector
-
プロトコルの完全なデコードを待たずにカーネルがパケットヘッダーを処理する必要がある場合、これらは
破棄されます。たとえば、これは、tcサブシステム、ボンディングのルーティング、またはパケットのハッシュを計算する際に発生します。この場合、カーネルはパケットヘッダーを解析し、パケットヘッダーからの情報を使用して内部構造を埋めます。この内部解析は、BPF_PROG_TYPE_FLOW_DISSECTORプログラムを使用して置き換えることができます。RHEL の eBPF では、TCP および UDP を IPv4 および IPv6 上でのみ破棄できます。 - TCP 輻輳制御
-
struct tcp_congestion_oopsコールバックを実装するBPF_PROG_TYPE_STRUCT_OPSプログラムのグループを使用して、カスタム TCP 輻輳制御アルゴリズムを作成できます。この方法を実装するアルゴリズムは、ビルトインのカーネルアルゴリズムとともにシステムで利用できます。 - カプセル化によるルート
以下のいずれかの eBPF プログラムタイプは、トンネルのカプセル化属性として、ルーティングテーブルのルートに割り当てることができます。
-
BPF_PROG_TYPE_LWT_IN -
BPF_PROG_TYPE_LWT_OUT -
BPF_PROG_TYPE_LWT_XMIT
このような eBPF プログラムの機能は特定のトンネル設定に限定され、汎用のカプセル化またはデシリアライズソリューションの作成はできません。
-
- ソケットルックアップ
-
bindシステムコールの制限を回避するには、BPF_PROG_TYPE_SK_LOOKUPタイプの eBPF プログラムを使用します。このようなプログラムは、新しい受信 TCP 接続のリスニングソケットまたは UDP パケットの非接続ソケットを選択できます。