eBPF Program Types

On this page

First determine what object you need to see at which moment, then select the BPF type. Context, helper/kfunc, and return values each have specific contracts; changing only the ELF section name cannot perform type conversion.

The following table provides navigation for common types; for the complete mapping, see the libbpf Program Types Table.

Target to ConsultReading Location
Type Overview and XDP ExperimentsSections 1–2
Network Layer and Function Event TracingSections 3–4
LSM, struct_ops, and Interface LimitationsSections 5–6

1. Quick Reference for Common Types

Type/FamilyExecution Location and ContextPrimary Purpose
SOCKET_FILTERSocket receive filtering, __sk_buffDetermine the amount of data to pass to the socket
XDPSupported XDP data paths, xdp_mdEarly packet processing and redirection
SCHED_CLS / SCHED_ACTTC, __sk_buffClassification, actions, packet modification
KPROBEkprobe/kretprobe, uprobe/uretprobeDynamic function probing, architecture-dependent register context
TRACEPOINT / RAW_TRACEPOINTPredefined events or raw event argumentsEvent observation
TRACINGfentry/fexit, tp_btf, etc.BTF-typed function/event observation
PERF_EVENTSoftware/hardware performance eventsPeriodic or event-driven sampling
CGROUP_SKB / SOCK_ADDR, etc.cgroup-related network operationsSocket/address/traffic policies
SOCK_OPS / SK_MSG / SK_SKBSocket callbacks or message pathsConnection handling, message redirection, etc.
SK_LOOKUPSocket lookupSelect target socket in supported lookup paths
LSMSupported LSM hooksAudit and access control extensions
STRUCT_OPSSpecific kernel operation tablesImplement supported callbacks, e.g., congestion control, scheduling extensions
SYSCALLUser-space execution via corresponding BPF runtime interfaceSpecific BPF operations/loading logic, not seccomp
The meaning of the return value is determined by the attached interface XDP return XDP_PASS Continue into the protocol stack TC direct-action return TC_ACT_OK Process according to TC action semantics LSM MAC hook return 0 This check does not deny Program type, attach type, context, and return contract must be selected together.

2. XDP: Mode Determines "How Early"

Native/driver XDP usually runs on the driver receive path, before constructing a regular skb. Generic/SKB mode uses a later skb path; hardware offload is further limited by device support. Therefore, not all XDP programs can be written as "zero skb allocation and no function calls within NAPI."

ActionSubsequent Meaning
XDP_ABORTED / DROPAbnormal termination / Discard handling
XDP_PASSContinue to subsequent stack paths
XDP_TXSend back from the receiving device
XDP_REDIRECTRedirect to a prepared target

REDIRECT usually requires setting the target device, CPU, or AF_XDP via helpers first. Simply returning a constant cannot automatically generate targets or complete forwarding protocols.

Minimal Boundary Check Example

The following only checks that the currently directly accessible data contains at least one Ethernet header. It does not parse VLAN, IP, or multi-buffer complete packets, nor is it a deployable complete filtering policy.

#include <linux/bpf.h>
#include <linux/if_ether.h>

__attribute__((section("xdp"), used))
int check_ethernet_header(struct xdp_md *ctx)
{
    void *data = (void *)(long)ctx->data;
    void *end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;

    if ((void *)(eth + 1) > end)
        return XDP_DROP;
    return XDP_PASS;
}

char bpf_license[] __attribute__((section("license"), used)) = "GPL";

Save as header.bpf.c, which can be compiled in a Clang environment with Linux UAPI headers and a BPF backend:

clang -O2 -g -target bpf -Wall -Wextra -Werror -c header.bpf.c -o header.bpf.o

Generating the ELF only verifies the compilation process; actual loading requires the verifier, and attachment requires permissions and device support. Some distributions may require supplementing the corresponding architecture UAPI include paths. Adjusting helpers such as packet head may change data pointer validity; subsequent access should re-acquire pointers and re-prove boundaries.

The following only takes the four bytes of source and destination ports, calculating the required boundaries for each. After IHL changes, the previous check that held for the minimum IPv4 header may not cover the new port location.

Preparing the visual
Why is a fixed check of 20 bytes insufficient to find ports?

The IPv4 header length is 4×IHL; port positions cannot always be hardcoded as Ethernet+20. Before reading ports, a valid IHL and corresponding data_end boundary proof are required.

3. TC and cgroup Are Not Network Hooks at the Same Level

TC operates on the skb path and can leverage richer network context. The interpretation of SCHED_CLS returns depends on the attachment mode; direct-action uses TC_ACT_* semantics, and traditional classifier results cannot be directly applied with the same interpretation. When updating attachments, consider whether the target system uses traditional TC or newer supported interfaces like link/TCX.

cgroup network programs provide checks around cgroup and socket associations, such as creation, bind/connect addresses, and send/receive traffic. The association lifecycle and inheritance rules of sockets affect which cgroup they belong to; moving a process does not mean all existing sockets immediately re-associate as intuition might suggest.

CGROUP_SKB is not attached to the net_cls controller on cgroup v1, nor can it be generalized as "the only hook through which all container packets pass." Actual network products often combine TC, XDP, cgroup, and socket-level programs; one cannot assert that all policies are implemented by a single type based solely on the product name.

4. Function and Event Tracing: Stability and Overhead Must Be Viewed Separately

kprobe uses architecture-dependent register states; BPF's R0–R10 virtual registers are not the original parameter registers of the probed C function. Parameters should be accessed via corresponding tracing macros/contexts, rather than writing "R0–R5 are the function arguments."

kretprobe observes returns and may need to be correlated with entry state; function inlining, prohibited probe locations, tail calls, and target implementation changes all affect coverage. uprobe/uretprobe perform similar probing on user-space code; suitability depends on trigger frequency and measured overhead, and they are not universally unsuitable for production.

tracepoints provide explicitly named events and fields, which are usually easier to maintain than relying on arbitrary internal functions; however, trace event formats do not constitute a stable UAPI that never changes across all versions. Actual fields can be found in tracefs events/.../format. The context representation differs for raw tracepoints, regular tracepoints, and tp_btf.

Typed Tracing: Having BTF Requires Attachable Targets

fentry/fexit leverage BPF trampolines and target BTF, usually facilitating type-based reading of function arguments and return information, but require corresponding kernel, target function, and BTF support. "Having BTF" does not mean all functions can be attached. See Tracing and Debugging.

5. LSM, struct_ops, and SYSCALL

LSM programs define context based on specific hook parameters; there is no single generic bpf_lsm_ctx structure that covers all hook fields. Attachment and return semantics for system-wide MAC and cgroup LSM should be consulted separately; do not mix the meanings of 0/1/-errno. See LSM BPF.

struct_ops only implements explicitly supported kernel operation tables and callbacks; it does not allow arbitrary replacement of any kernel function pointers. Whether callbacks allow sleeping, how objects are verified, and who manages registration lifetime are all dictated by the target interface.

The name BPF_PROG_TYPE_SYSCALL is misleading: it does not filter user processes at every system call entry, but rather refers to a program category executed by user-space via corresponding runtime interfaces, possessing specific helper/kfunc capabilities. The source code can be read from bpf_syscall_prog_ops in kernel/bpf/syscall.c and the test-run path. System call restrictions should be consulted via seccomp; system call observation can use tracepoints, etc.

6. Helper/kfunc Availability Cannot Be Judged by Name Alone

Whether the same helper is allowed depends on the program type, attach type, context, permissions, and kernel capabilities; kfuncs may also have stricter internal interface constraints. Sleepable BPF is also only valid in supported programs and call sites.

Attribution Boundary: The Current Task Is Not Necessarily the Business Owner of the Packet

The current PID/comm obtained in the network softirq may not be the business process that generated the packet. Even if the helper call is legal, the observation semantics may not match expectations. Clarify object ownership first, then decide on the statistics key, to avoid creating charts that appear precise but have incorrect attribution.