Linuxにおける利用が急速に増えている「Berkeley Packet Filter(BPF)」について、基礎から応用まで幅広く紹介する連載。今回は、BPFでできること、BPFのプログラムタイプについて。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
Linuxにおける利用が急速に増えている「Berkeley Packet Filter(BPF)」について、基礎から応用まで幅広く紹介する連載「Berkeley Packet Filter(BPF)入門」。前回までは、BPFの基本やBPFのプログラムの作成方法を説明しました。今回から、「LinuxのBPFで何ができるのか」について詳しく見ていきます。
なお本稿では、Linux 5.3のソースコードを参照しています。
BPFプログラム実行の流れをおさらいしましょう。
ユーザーはBPFプログラムを作成し、システムコールを利用してそれをLinuxカーネル内に登録します(図の【1】)。そうして登録されたBPFプログラムは、対応するイベントが発生すると、Linuxの中で引数が1つ、戻り値も1つの関数として実行されます(図の【2】)。BPFプログラムは実行中にカーネル内のヘルパー関数を呼び出すことができます。例えば、ヘルパー関数を利用して「BPFマップ」と呼ばれるユーザー空間と共有できるデータ構造にアクセスすることが可能です(図の【3】)。
BPFプログラムの実行が終了すると、BPFプログラムの戻り値に応じてカーネルは処理を継続します。BPFプログラム自体は状態を持ちませんが、BPFマップを利用することで情報を記録できます。
このとき、「BPFが何を行うのか」「BPFで何ができるのか」は以下の項目で決まります。
LinuxのBPFには「プログラムタイプ」があり、そのプログラムタイプごとに上記の項目が定義されます。また、BPFをカーネル内にロードする際は、検証機はプログラムタイプに応じた検証を実施します。
BPFのプログラムタイプは「include/uapi/linux/bpf.h」で定義されています。
Linux 5.3で利用可能なBPFのプログラムタイプには、下記の26種類があります。
enum bpf_prog_type {
BPF_PROG_TYPE_UNSPEC,
BPF_PROG_TYPE_SOCKET_FILTER,
BPF_PROG_TYPE_KPROBE,
BPF_PROG_TYPE_SCHED_CLS,
BPF_PROG_TYPE_SCHED_ACT,
BPF_PROG_TYPE_TRACEPOINT,
BPF_PROG_TYPE_XDP,
BPF_PROG_TYPE_PERF_EVENT,
BPF_PROG_TYPE_CGROUP_SKB,
BPF_PROG_TYPE_CGROUP_SOCK,
BPF_PROG_TYPE_LWT_IN,
BPF_PROG_TYPE_LWT_OUT,
BPF_PROG_TYPE_LWT_XMIT,
BPF_PROG_TYPE_SOCK_OPS,
BPF_PROG_TYPE_SK_SKB,
BPF_PROG_TYPE_CGROUP_DEVICE,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_RAW_TRACEPOINT,
BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
BPF_PROG_TYPE_LWT_SEG6LOCAL,
BPF_PROG_TYPE_LIRC_MODE2,
BPF_PROG_TYPE_SK_REUSEPORT,
BPF_PROG_TYPE_FLOW_DISSECTOR,
BPF_PROG_TYPE_CGROUP_SYSCTL,
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
BPF_PROG_TYPE_CGROUP_SOCKOPT,
};
それぞれのプログラムタイプについて残念ながら、「何が引数として与えられるのか」「戻りは何を意味するのか」などの情報はあまりまとまっていません。カーネルのサンプルプログラムを見たり、ヘルパー関数の引数から推測したり、カーネルのソースを直接確認したりするといいでしょう。
それぞれのプログラムタイプで利用可能なヘルパー関数に関しては下記に情報があります。
以降、主要なプログラムタイプについて、どこで何に利用されているのか見ていきます。
2018年上半期に話題になったSpectreとその変異、Linuxカーネルでの対応まとめ
2017年版Linuxカーネル開発レポート公開――支援している企業トップ10とは?
Linuxカーネルのソースコードを読んで、システムコールを探るCopyright © ITmedia, Inc. All Rights Reserved.