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, };
それぞれのプログラムタイプについて残念ながら、「何が引数として与えられるのか」「戻りは何を意味するのか」などの情報はあまりまとまっていません。カーネルのサンプルプログラムを見たり、ヘルパー関数の引数から推測したり、カーネルのソースを直接確認したりするといいでしょう。
それぞれのプログラムタイプで利用可能なヘルパー関数に関しては下記に情報があります。
以降、主要なプログラムタイプについて、どこで何に利用されているのか見ていきます。
Copyright © ITmedia, Inc. All Rights Reserved.