BPF 프로그램의 종류는 다양하다. BPF 프로그램은 이벤트를 중심으로 작성되는데, 프로그램 타입에 따라 사용할 수 있는 이벤트가 제한적이므로 작성하고자 하는 프로그램이 어떤 범주에 속하는지 잘 알고 있어야 한다.
작성한 프로그램은 해당하는 이벤트가 발생할 때 실행되고, 실행 시점에 프로그램에서 필요로 하는 정보가 컨텍스트로 제공될 것이다.
프로그램 타입
커널 내 소스에는 커널에서 지원하는 BPF 프로그램의 타입 전체가 나열되어 있다.
아래 표와 같이 이 프로그램 타입들을 범주별로 묶을 수 있다.
범주 | 프로그램 타입 |
---|---|
소켓 관련 | SOCKET_FILTER SK_SKB SOCK_OPS |
TC 관련 | BPF_PROG_SCHED_CLS BPF_PROG_SCHED_ACT |
XDP 관련 | BPF_PROG_TYPE_XDP |
트레이싱 관련 | BPF_PROG_TYPE_KPROBE BPF_PROG_TYPE_TRACEPOINT BPF_PROG_TYPE_PERF_EVENT |
CGROUP 관련 | BPF_PROG_TYPE_CGROUP_SKB BPF_PROG_TYPE_CGROUP_SOCK BPF_PROG_TYPE_CGROUP_DEVICE |
터널링 관련 | BPF_PROG_TYPE_LWT_IN BPF_PROG_TYPE_LWT_OUT BPF_PROG_TYPE_LWT_XMIT BPF_PROG_TYPE_LWT_SEGGLOCAL |
타입별 특징
각 타입별로 신경써야 하는 부분은 다음 3가지이다.
- 어떤 역할이며, 언제 프로그램이 실행되는가?
- 어떻게 커널에 로딩하는가?
- 어떤 컨텍스트가 제공되는가?
BPF_PROG_TYPE_KPROBE 타입의 프로그램을 예로 들어 살펴보자.
-
어떤 역할이며, 언제 프로그램이 실행되는가?
BPF_PROG_TYPE_KPROBE
는 이름 그대로kprobe
를 활용하는 프로그램 타입이다.kprobe
는 커널의 함수 진입점에 바인딩되는 이벤트로서 커널 내 특정 함수 호출 정보를 제공할 수 있다.
-
어떻게 커널에 로딩하는가?
-
kprobe
에 관련된 인터페이스는 sysfs 밑의 tracef애 있다. -
tracefs는 트레이싱을 위한 특별한 파일 시스템으로, 바인딩을 위한 ID를 tracefs를 통해 발급받을 수 있다. 보통은 debugfs 아래에 마운트되어 있다.
-
이렇게 발급받은 ID는 BPF 프로그램을 로드할 때
sys_perf_event_open()
에 해당 id를 찾아서 전달된다. -
BPF 바이너리는 이벤트가 바인딩되기 전에 커널로 먼저 로딩되어야 한다.
do_load_bpf_file()
함수에서 주어진 경로의 ELF 바이너리를 읽어서 프로그램과 맵, 그리고 그외 ELF 섹션에 기술된 라이선스 및 버전 등을 추출한다. -
필요한 정보를 처리하고 나면
load_and_attach()
가 호출되며, 다음 코드 블럭에서 프로그램을 커널로 로딩한다. -
bpf_load_program()
은 bpf() 시스템 콜을 추상화해주는libbpf
라이브러리에서 제공하는 함수이다.
-
-
어떤 컨텍스트가 제공되는가?
-
전달되는 컨텍스트는
struct pt_regs *ctx
이다.-
이 구조체는 레지스터를 추상화한 구조체로서 이를 통해 함수 호출 시 전달되는 매개변수, 레지스터 상태, 함수 실행 전후의 컨텍스트 등을 확인할 수 있다.
-
-
(BCC를 사용하면 구조체에서 정보를 가져오는 부분도 추상화되어 작동한다.)
-
참고