Linux / Jul 24, 2026 / 11 min
eBPF Program Types: XDP, TC, Tracing, and Security Hooks
XDP와 TC부터 Kprobe, Tracepoint, Uprobe, Cgroup, LSM까지 eBPF 프로그램의 실행 위치와 용도를 정리한다.
Summary
eBPF 프로그램은 아무 위치에서나 같은 방식으로 실행되지 않는다. 프로그램을 load할 때 지정하는 Program Type에 따라 사용할 수 있는 context, helper, return value와 연결 가능한 kernel hook이 달라진다.
자주 등장하는 영역은 다음과 같다.
| Area | Representative Hooks or Types | Main Purpose |
|---|---|---|
| Early networking | XDP | NIC receive path에서 빠른 drop, redirect, load balancing |
| Network stack | TC / TCX | Ingress·egress policy, packet rewrite, QoS, encapsulation |
| Socket layer | Socket Filter, Cgroup Socket, SK Lookup | Packet filtering, socket 생성·연결 제어, local socket 선택 |
| Kernel tracing | Kprobe, Tracepoint, Raw Tracepoint, fentry/fexit | Kernel event와 function 관측 |
| User-space tracing | Uprobe, Uretprobe, USDT | Application과 library function 관측 |
| Security | BPF LSM, Cgroup Device | File·process·device 접근 감사와 차단 |
| Profiling | Perf Event | CPU counter와 sampling event 기반 profiling |
User Space
│
Loader: libbpf, bpftool, bpftrace, Cilium
│
────┼──────────────── Kernel ─────────────────
│
├── Network path: XDP → TC ingress → ... → TC egress
├── Kernel events: Tracepoint, Kprobe, fentry/fexit
├── Applications: Uprobe, Uretprobe, USDT
├── Security: LSM and cgroup hooks
└── Performance: Perf Event
XDP와 TC는 경쟁 기술이라기보다 서로 다른 packet path에 연결되는 프로그램이다. XDP는 가능한 한 이른 지점에서 단순하고 빠른 결정을 내리고, TC는 sk_buff와 ingress·egress context를 이용해 더 풍부한 network 처리를 수행한다.
기본적인 eBPF 실행 구조와 Map이 먼저 필요하다면 eBPF 기본 개념을 함께 참고할 수 있다.
Program Type, Hook, and Attach Type
eBPF 관련 문서에서는 type과 hook이라는 단어가 섞여 사용되지만 정확히는 구분할 필요가 있다.
Program Type
Program Type은 BPF_PROG_LOAD로 프로그램을 kernel에 적재할 때 지정하는 값이다.
BPF_PROG_TYPE_XDP
BPF_PROG_TYPE_SCHED_CLS
BPF_PROG_TYPE_TRACEPOINT
BPF_PROG_TYPE_KPROBE
BPF_PROG_TYPE_TRACING
BPF_PROG_TYPE_LSM
Verifier는 Program Type을 기준으로 다음을 검사한다.
- 프로그램이 받는 context 구조체
- 호출 가능한 BPF helper와 kfunc
- 허용된 return value
- 연결 가능한 hook과 attach mechanism
예를 들어 XDP 프로그램은 packet을 xdp_md context로 보고 XDP_PASS, XDP_DROP, XDP_REDIRECT 같은 action을 반환한다. 같은 코드를 LSM hook에 그대로 연결할 수는 없다.
Hook and Attach Type
Hook은 프로그램이 실제 실행되는 kernel 지점이다. Attach Type은 하나의 Program Type 안에서 어느 세부 hook과 동작에 연결할지 표현한다.
Program Type: BPF_PROG_TYPE_CGROUP_SOCK_ADDR
Attach Type: BPF_CGROUP_INET4_CONNECT
Hook: IPv4 connect() attempted by a task in the cgroup
libbpf의 ELF section name은 Program Type과 자동 연결 정보를 함께 표현한다.
| ELF Section | Program Type and Attachment |
|---|---|
SEC("xdp") | XDP program을 network device의 XDP hook에 연결 |
SEC("tcx/ingress") | SCHED_CLS program을 TCX ingress에 연결 |
SEC("tracepoint/sched/sched_switch") | Tracepoint program을 scheduler event에 연결 |
SEC("kprobe/tcp_connect") | Kprobe 계열 program을 kernel function에 연결 |
SEC("fentry/tcp_connect") | TRACING program을 BTF 기반 function entry에 연결 |
SEC("uprobe//usr/lib/libssl.so:SSL_read") | Kprobe 계열 program을 user-space symbol에 연결 |
SEC("lsm/file_open") | LSM program을 security hook에 연결 |
따라서 Kprobe와 Uprobe는 서로 다른 실행 위치지만 libbpf에서 둘 다 BPF_PROG_TYPE_KPROBE 계열로 load될 수 있다. 반대로 cgroup은 하나의 Program Type이 아니라 여러 cgroup 관련 Program Type과 Attach Type을 묶어 부르는 경우가 많다.
Network Program Types
XDP
XDP는 network device의 receive path 초기에 실행된다. Native XDP에서는 driver가 RX frame을 받은 뒤 sk_buff를 만들기 전에 프로그램이 실행되므로 불필요한 packet을 매우 이른 시점에 제거할 수 있다.
NIC RX Queue
│
Driver
│
XDP
├── XDP_DROP
├── XDP_PASS
├── XDP_TX
└── XDP_REDIRECT
│
Linux Network Stack
| Action | Meaning |
|---|---|
XDP_PASS | Packet을 일반 Linux network stack으로 전달한다. |
XDP_DROP | Packet을 이른 지점에서 폐기한다. |
XDP_TX | Packet을 수신한 device로 다시 전송한다. |
XDP_REDIRECT | 다른 device, CPU 또는 AF_XDP socket 등으로 보낸다. |
XDP_ABORTED | XDP_DROP처럼 폐기하고 exception tracepoint를 남긴다. |
대표적인 사용 사례는 DDoS filtering, simple ACL, L4 load balancing, fast forwarding과 traffic sampling이다.
XDP 실행 방식은 환경에 따라 달라진다.
- Native XDP: Driver가 XDP를 지원하며 가장 일반적인 고성능 경로다.
- Generic XDP: Driver 지원이 없을 때 network stack의 generic fallback에서 실행한다.
- Offloaded XDP: 지원되는 SmartNIC hardware로 프로그램을 offload한다.
Native XDP는 sk_buff가 생성되기 전에 실행되므로 socket, routing과 protocol stack의 풍부한 metadata가 아직 준비되지 않는다. 반면 Generic XDP는 이미 sk_buff를 사용하는 fallback 경로이므로 Native XDP와 같은 성능 특성을 기대하면 안 된다. 또한 기본 XDP hook은 ingress 중심이므로 일반적인 host egress 처리에는 TC가 더 적합할 수 있다.
TC and TCX
TC eBPF 프로그램은 BPF_PROG_TYPE_SCHED_CLS를 주로 사용하며 network device의 ingress와 egress에 연결할 수 있다. 프로그램은 __sk_buff context를 통해 packet과 mark, priority, VLAN 같은 skb metadata를 다룬다. TC ingress는 sk_buff가 생성된 뒤 protocol processing과 netfilter보다 앞선 network path에서 실행되고, TC egress는 packet이 driver로 전달되기 전의 후반 경로에서 실행된다.
Incoming Packet
│
XDP
│
Kernel creates an sk_buff
│
TC Ingress
│
Routing / netfilter / sockets
│
TC Egress
│
Network Device
대표 사용 사례는 다음과 같다.
- Kubernetes NetworkPolicy
- Packet marking과 rewriting
- VXLAN·Geneve encapsulation과 decapsulation
- QoS classification과 traffic control
- Ingress·egress observability
- Container와 host 사이의 forwarding과 load balancing
전통적으로 clsact qdisc에 TC filter로 연결했으며 최신 kernel과 libbpf에서는 link 기반의 TCX ingress·egress attachment를 사용할 수 있다. 최신 libbpf 문서에서 bare SEC("tc"), SEC("classifier"), SEC("action") section convention을 deprecated로 표시하는 것은 TC packet processing 자체가 폐기됐다는 뜻이 아니라, 지원되는 환경에서 SEC("tcx/ingress")와 SEC("tcx/egress") attachment를 권장한다는 의미다. TCX를 지원하지 않는 kernel에서는 기존 clsact 방식이 여전히 필요하다.
XDP and TC Together
XDP와 TC는 실행 지점과 context가 다르므로 함께 사용할 수 있다.
Packet
│
XDP
├── Obvious attack traffic → DROP
└── Valid traffic → PASS
│
TC Ingress
├── Apply network policy
├── Read or set skb metadata
└── Redirect or decapsulate
│
TC Egress
├── Encapsulate
├── Apply egress policy
└── Mark for QoS
XDP만 사용하면 packet을 일찍 처리할 수 있지만 나중에 생성되는 context를 사용할 수 없다. TC만 사용하면 풍부한 context를 얻지만 drop할 packet도 sk_buff 생성 지점까지 도달한다. Cilium 같은 networking platform은 feature와 device 지원 상태에 따라 두 hook을 선택하거나 조합한다.
Socket Filter
BPF_PROG_TYPE_SOCKET_FILTER는 socket으로 전달되는 packet을 검사해 유지할 byte 수 또는 drop 여부를 결정한다. Packet capture에서 kernel이 모든 packet을 user space로 복사하기 전에 필요한 traffic만 고르는 데 사용할 수 있다.
Packet → Socket Filter → Matching packet → User space
└→ Non-matching packet → Drop
XDP가 device receive path에서 system-wide forwarding 결정을 내리는 것과 달리 Socket Filter는 특정 socket에 도달하는 traffic을 필터링한다.
Cgroup and Socket Families
Network stack의 socket 단계에는 cgroup 기반 hook과 socket map 또는 network namespace 기반 hook이 함께 존재한다. Cgroup BPF 자체도 하나의 단일 type이 아니라 task가 속한 cgroup을 기준으로 socket과 packet 동작을 제어하는 여러 Program Type의 집합이다.
| Family | Example Hook | Purpose |
|---|---|---|
CGROUP_SKB | Ingress / egress skb | Cgroup 단위 packet 허용과 통계 |
CGROUP_SOCK_ADDR | connect4, bind6 | Connection과 bind 주소 제어·변환 |
CGROUP_SOCK | Socket create/release | Socket 생성 정책과 metadata 설정 |
SOCK_OPS | TCP state transition | TCP 상태·metric 관측과 socket option 조정 |
SK_MSG | Sockmap message path | Socket 사이 message redirect와 policy |
SK_LOOKUP | Local TCP/UDP socket lookup | 수신 packet을 처리할 local socket 선택 |
Cgroup BPF가 CPU와 memory quota를 대신 관리한다는 의미는 아니다. CPU·memory 자원 제한은 cgroup controller의 역할이고, BPF hook은 주로 network, socket, device와 일부 sysctl 접근에 programmable policy를 추가한다.
이 표의 모든 항목이 cgroup에 연결되는 것은 아니다. SOCK_OPS는 cgroup에 attach하지만, SK_MSG는 SOCKMAP 또는 SOCKHASH의 message path에, SK_LOOKUP은 network namespace의 local socket lookup hook에 attach한다.
Tracing Program Types
Tracepoint and Raw Tracepoint
Tracepoint는 kernel이 미리 정의한 event다.
sched:sched_switch
syscalls:sys_enter_openat
net:netif_receive_skb
BPF_PROG_TYPE_TRACEPOINT는 tracepoint가 제공하는 형식화된 context를 사용한다. Kernel 내부 function 이름에 직접 의존하는 Kprobe보다 의도된 관측 interface에 연결되므로 일반적으로 version 변화에 더 강하다. 다만 모든 tracepoint가 영구적인 user-space ABI를 보장하는 것은 아니므로 대상 kernel의 event 이름과 format은 확인해야 한다.
Raw Tracepoint는 더 낮은 수준의 raw argument를 제공해 변환 계층을 줄일 수 있지만, 개발자가 argument type과 kernel 변화에 더 주의해야 한다. raw = 항상 더 빠르고 더 좋다기보다는 필요한 context와 portability를 기준으로 선택해야 한다.
Kprobe and Kretprobe
Kprobe는 실행 중인 kernel function의 entry 또는 특정 offset에 동적으로 연결된다. Kretprobe는 function return 시점에 실행된다.
Application calls connect()
│
Kernel tcp_connect()
├── Kprobe: arguments and entry time
│
└── Kretprobe: return value
Latency를 계산하려면 Kprobe에서 저장한 entry timestamp를 Kretprobe에서 읽어 두 시점을 연결해야 한다. Tracepoint가 없는 내부 경로까지 관찰할 수 있어 debugging에 유용하지만 모든 kernel function에 항상 연결할 수 있는 것은 아니다. Inline된 function, probe 제한이 있는 function과 kernel version에 따라 이름이나 argument가 바뀐 function은 주의해야 한다.
fentry and fexit
fentry와 fexit은 BPF_PROG_TYPE_TRACING과 kernel BTF를 이용해 function entry와 exit에 연결한다. 지원되는 kernel에서는 typed argument 접근과 낮은 instrumentation overhead 때문에 Kprobe보다 선호될 수 있다.
| Hook | Timing | Typical Data |
|---|---|---|
fentry | Function entry | Typed function arguments |
fexit | Function exit | Typed function arguments와 return value |
fexit이 duration을 자동으로 제공하는 것은 아니다. Latency가 필요하면 fentry에서 timestamp를 저장하고 fexit에서 꺼내 계산해야 한다. BTF와 target function 지원이 필요하므로 구형 kernel이나 BTF가 없는 환경에서는 Kprobe가 더 현실적인 선택일 수 있다.
Uprobe, Uretprobe, and USDT
Uprobe는 executable이나 shared library의 user-space function entry에, Uretprobe는 return 지점에 연결된다.
nginx / OpenSSL / application
│
SSL_read()
├── Uprobe
└── Uretprobe
Application latency, function argument, return value와 library 호출을 관찰할 수 있다. Binary symbol, build ID, stripped binary, ABI와 application version 변화가 attachment에 영향을 준다.
USDT는 application이 의도적으로 노출한 static probe point다. 사용할 수 있는 USDT probe가 있다면 임의 function offset을 추적하는 Uprobe보다 의미가 명확하고 version 호환성을 관리하기 쉽다.
Perf Event
BPF_PROG_TYPE_PERF_EVENT는 perf hardware·software event가 sample 또는 overflow를 발생시킬 때 실행된다.
- CPU cycles와 instructions
- Cache miss와 branch miss
- Software clock과 CPU profiling sample
주기적인 stack sample을 Map에 집계하면 flame graph용 profiling data를 만들 수 있다. Event 지원과 정확도는 CPU PMU, kernel 설정과 virtualization 환경에 따라 달라진다.
Security Program Types
BPF LSM
BPF_PROG_TYPE_LSM은 Linux Security Module hook에 연결되어 system-wide audit 또는 MAC policy를 구현한다.
Process attempts file access
│
LSM Hook
│
BPF Program
├── Allow
└── Deny with an error
File open과 permission, process credential, socket security 같은 LSM hook에서 context를 관찰하고 일부 동작을 차단할 수 있다. BPF LSM 프로그램은 GPL-compatible license 선언도 필요하다. Kernel의 BPF LSM 지원과 적절한 privilege가 필요하며, 잘못된 deny policy는 system process까지 막을 수 있으므로 audit mode와 좁은 범위에서 먼저 검증해야 한다.
Cgroup Device and Sysctl
BPF_PROG_TYPE_CGROUP_DEVICE는 cgroup 안의 process가 특정 device file을 생성하거나 읽고 쓸 수 있는지 제어한다. Device type과 major·minor number, access mode를 기준으로 판단한다.
BPF_PROG_TYPE_CGROUP_SYSCTL은 cgroup의 process가 sysctl을 읽거나 쓸 때 실행된다. Kernel 문서는 이 Program Type을 sysctl 제한을 위한 security mechanism으로 사용하지 말라고 명시하며, trusted root 환경에서 monitoring과 value validation 용도로 사용할 것을 권장한다.
Choosing the Right Hook
| Question | First Candidate |
|---|---|
| NIC에서 들어온 공격 packet을 가장 일찍 drop해야 하는가? | XDP |
| Ingress와 egress에서 policy, rewrite, encapsulation이 필요한가? | TC / TCX |
| 특정 socket으로 복사할 packet만 고르고 싶은가? | Socket Filter |
| Container group의 connect·bind를 제어하고 싶은가? | Cgroup Socket hooks |
| 안정적으로 정의된 kernel event를 관찰하고 싶은가? | Tracepoint |
| Tracepoint가 없는 kernel 내부 function을 조사해야 하는가? | fentry/fexit 또는 Kprobe/Kretprobe |
| Application library function을 관찰해야 하는가? | Uprobe/Uretprobe 또는 USDT |
| File·process 접근을 감사하거나 차단해야 하는가? | BPF LSM |
| CPU와 cache 성능을 sampling해야 하는가? | Perf Event |
선택할 때는 실행 위치만 보지 말고 다음 조건을 함께 확인한다.
- 사용 중인 kernel version과 BTF 제공 여부
- Network driver의 native XDP 지원 여부
- Program Type에서 허용되는 helper와 context
- Enforcement가 필요한지 observability만 필요한지
- Event 빈도와 프로그램 실행 비용
- Kernel·application upgrade에 대한 attachment 안정성
Inspection Commands
현재 kernel이 지원하는 기능과 load된 프로그램은 bpftool로 확인할 수 있다.
sudo bpftool feature probe
sudo bpftool prog list
sudo bpftool link list
sudo bpftool map list
sudo bpftool net
Tracing event와 TC filter는 다음과 같이 확인할 수 있다.
sudo cat /sys/kernel/tracing/available_events
sudo bpftrace -l 'tracepoint:*'
sudo tc filter show dev eth0 ingress
sudo tc filter show dev eth0 egress
bpftool prog list의 type은 Program Type을 보여주고, bpftool link list나 bpftool net은 어디에 연결됐는지 파악하는 데 도움을 준다. Kernel과 attachment 방식에 따라 모든 연결이 같은 명령에 나타나지는 않으므로 tool 하나의 출력만으로 전체 상태를 판단하면 안 된다.
Tool Mapping
| Tool or Platform | Commonly Used Areas |
|---|---|
| Cilium | XDP, TC, cgroup socket 계열을 이용한 networking과 policy |
| bpftrace / BCC | Kprobe, Tracepoint, Uprobe, Perf Event 기반 tracing |
| Tetragon | Kprobe, tracing, LSM 계열을 이용한 runtime observability와 enforcement |
| Profilers | Perf Event, stack sampling과 user-space probes |
하나의 제품이 Program Type 하나만 사용하는 것은 아니다. Cilium 같은 platform은 service load balancing, network policy와 socket acceleration을 서로 다른 hook의 여러 eBPF 프로그램으로 구현하고 Map을 통해 상태를 공유한다.
Key Takeaways
- Program Type은 context, helper, return value와 연결 가능한 hook의 범위를 정한다.
- Hook은 프로그램이 실행되는 위치이며 Attach Type은 같은 Program Type의 세부 연결 방식을 표현한다.
- XDP는 ingress 초기의 빠른 처리에, TC는 ingress·egress의 풍부한 skb 처리에 적합하다.
- XDP와 TC는 서로 대체하기보다 한 packet path에서 보완적으로 사용할 수 있다.
- Tracepoint는 정의된 event, Kprobe는 동적 kernel function, Uprobe는 user-space function을 관찰한다.
- 지원되는 환경에서는 BTF 기반 fentry/fexit이 Kprobe보다 typed context와 낮은 overhead를 제공할 수 있다.
- Cgroup은 단일 Program Type이 아니라 socket, packet, device와 sysctl hook의 여러 type을 포함한다.
- BPF LSM은 관측뿐 아니라 deny policy를 적용할 수 있으므로 더 신중한 검증이 필요하다.
Review Questions
- Program Type, Hook, Attach Type은 각각 무엇을 결정하는가?
- XDP가 TC보다 빠를 수 있지만 사용할 수 있는 context가 적은 이유는 무엇인가?
- TC ingress와 egress를 모두 사용할 수 있다는 점은 어떤 정책에 유리한가?
- Tracepoint, Kprobe, fentry를 선택할 때 안정성과 kernel 지원을 어떻게 비교해야 하는가?
- Cgroup BPF가 CPU와 memory resource controller 자체는 아닌 이유는 무엇인가?