Blame man/man8/tc-bpf.8

Packit Service 3880ab
.TH "BPF classifier and actions in tc" 8 "18 May 2015" "iproute2" "Linux"
Packit Service 3880ab
.SH NAME
Packit Service 3880ab
BPF \- BPF programmable classifier and actions for ingress/egress
Packit Service 3880ab
queueing disciplines
Packit Service 3880ab
.SH SYNOPSIS
Packit Service 3880ab
.SS eBPF classifier (filter) or action:
Packit Service 3880ab
.B tc filter ... bpf
Packit Service 3880ab
[
Packit Service 3880ab
.B object-file
Packit Service 3880ab
OBJ_FILE ] [
Packit Service 3880ab
.B section
Packit Service 3880ab
CLS_NAME ] [
Packit Service 3880ab
.B export
Packit Service 3880ab
UDS_FILE ] [
Packit Service 3880ab
.B verbose
Packit Service 3880ab
] [
Packit Service 3880ab
.B direct-action
Packit Service 3880ab
|
Packit Service 3880ab
.B da
Packit Service 3880ab
] [
Packit Service 3880ab
.B skip_hw
Packit Service 3880ab
|
Packit Service 3880ab
.B skip_sw
Packit Service 3880ab
] [
Packit Service 3880ab
.B police
Packit Service 3880ab
POLICE_SPEC ] [
Packit Service 3880ab
.B action
Packit Service 3880ab
ACTION_SPEC ] [
Packit Service 3880ab
.B classid
Packit Service 3880ab
CLASSID ]
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc action ... bpf
Packit Service 3880ab
[
Packit Service 3880ab
.B object-file
Packit Service 3880ab
OBJ_FILE ] [
Packit Service 3880ab
.B section
Packit Service 3880ab
CLS_NAME ] [
Packit Service 3880ab
.B export
Packit Service 3880ab
UDS_FILE ] [
Packit Service 3880ab
.B verbose
Packit Service 3880ab
]
Packit Service 3880ab
Packit Service 3880ab
.SS cBPF classifier (filter) or action:
Packit Service 3880ab
.B tc filter ... bpf
Packit Service 3880ab
[
Packit Service 3880ab
.B bytecode-file
Packit Service 3880ab
BPF_FILE |
Packit Service 3880ab
.B bytecode
Packit Service 3880ab
BPF_BYTECODE ] [
Packit Service 3880ab
.B police
Packit Service 3880ab
POLICE_SPEC ] [
Packit Service 3880ab
.B action
Packit Service 3880ab
ACTION_SPEC ] [
Packit Service 3880ab
.B classid
Packit Service 3880ab
CLASSID ]
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc action ... bpf
Packit Service 3880ab
[
Packit Service 3880ab
.B bytecode-file
Packit Service 3880ab
BPF_FILE |
Packit Service 3880ab
.B bytecode
Packit Service 3880ab
BPF_BYTECODE ]
Packit Service 3880ab
Packit Service 3880ab
.SH DESCRIPTION
Packit Service 3880ab
Packit Service 3880ab
Extended Berkeley Packet Filter (
Packit Service 3880ab
.B eBPF
Packit Service 3880ab
) and classic Berkeley Packet Filter
Packit Service 3880ab
(originally known as BPF, for better distinction referred to as
Packit Service 3880ab
.B cBPF
Packit Service 3880ab
here) are both available as a fully programmable and highly efficient
Packit Service 3880ab
classifier and actions. They both offer a minimal instruction set for
Packit Service 3880ab
implementing small programs which can safely be loaded into the kernel
Packit Service 3880ab
and thus executed in a tiny virtual machine from kernel space. An in-kernel
Packit Service 3880ab
verifier guarantees that a specified program always terminates and neither
Packit Service 3880ab
crashes nor leaks data from the kernel.
Packit Service 3880ab
Packit Service 3880ab
In Linux, it's generally considered that eBPF is the successor of cBPF.
Packit Service 3880ab
The kernel internally transforms cBPF expressions into eBPF expressions and
Packit Service 3880ab
executes the latter. Execution of them can be performed in an interpreter
Packit Service 3880ab
or at setup time, they can be just-in-time compiled (JIT'ed) to run as
Packit Service 3880ab
native machine code.
Packit Service 3880ab
.PP
Packit Service 3880ab
Currently, the eBPF JIT compiler is available for the following architectures:
Packit Service 3880ab
.IP * 4
Packit Service 3880ab
x86_64 (since Linux 3.18)
Packit Service 3880ab
.PD 0
Packit Service 3880ab
.IP *
Packit Service 3880ab
arm64 (since Linux 3.18)
Packit Service 3880ab
.IP *
Packit Service 3880ab
s390 (since Linux 4.1)
Packit Service 3880ab
.IP *
Packit Service 3880ab
ppc64 (since Linux 4.8)
Packit Service 3880ab
.IP *
Packit Service 3880ab
sparc64 (since Linux 4.12)
Packit Service 3880ab
.IP *
Packit Service 3880ab
mips64 (since Linux 4.13)
Packit Service 3880ab
.IP *
Packit Service 3880ab
arm32 (since Linux 4.14)
Packit Service 3880ab
.IP *
Packit Service 3880ab
x86_32 (since Linux 4.18)
Packit Service 3880ab
.PD
Packit Service 3880ab
.PP
Packit Service 3880ab
Whereas the following architectures have cBPF, but did not (yet) switch to eBPF
Packit Service 3880ab
JIT support:
Packit Service 3880ab
.IP * 4
Packit Service 3880ab
ppc32
Packit Service 3880ab
.PD 0
Packit Service 3880ab
.IP *
Packit Service 3880ab
sparc32
Packit Service 3880ab
.IP *
Packit Service 3880ab
mips32
Packit Service 3880ab
.PD
Packit Service 3880ab
.PP
Packit Service 3880ab
eBPF's instruction set has similar underlying principles as the cBPF
Packit Service 3880ab
instruction set, it however is modelled closer to the underlying
Packit Service 3880ab
architecture to better mimic native instruction sets with the aim to
Packit Service 3880ab
achieve a better run-time performance. It is designed to be JIT'ed with
Packit Service 3880ab
a one to one mapping, which can also open up the possibility for compilers
Packit Service 3880ab
to generate optimized eBPF code through an eBPF backend that performs
Packit Service 3880ab
almost as fast as natively compiled code. Given that LLVM provides such
Packit Service 3880ab
an eBPF backend, eBPF programs can therefore easily be programmed in a
Packit Service 3880ab
subset of the C language. Other than that, eBPF infrastructure also comes
Packit Service 3880ab
with a construct called "maps". eBPF maps are key/value stores that are
Packit Service 3880ab
shared between multiple eBPF programs, but also between eBPF programs and
Packit Service 3880ab
user space applications.
Packit Service 3880ab
Packit Service 3880ab
For the traffic control subsystem, classifier and actions that can be
Packit Service 3880ab
attached to ingress and egress qdiscs can be written in eBPF or cBPF. The
Packit Service 3880ab
advantage over other classifier and actions is that eBPF/cBPF provides the
Packit Service 3880ab
generic framework, while users can implement their highly specialized use
Packit Service 3880ab
cases efficiently. This means that the classifier or action written that
Packit Service 3880ab
way will not suffer from feature bloat, and can therefore execute its task
Packit Service 3880ab
highly efficient. It allows for non-linear classification and even merging
Packit Service 3880ab
the action part into the classification. Combined with efficient eBPF map
Packit Service 3880ab
data structures, user space can push new policies like classids into the
Packit Service 3880ab
kernel without reloading a classifier, or it can gather statistics that
Packit Service 3880ab
are pushed into one map and use another one for dynamically load balancing
Packit Service 3880ab
traffic based on the determined load, just to provide a few examples.
Packit Service 3880ab
Packit Service 3880ab
.SH PARAMETERS
Packit Service 3880ab
.SS object-file
Packit Service 3880ab
points to an object file that has an executable and linkable format (ELF)
Packit Service 3880ab
and contains eBPF opcodes and eBPF map definitions. The LLVM compiler
Packit Service 3880ab
infrastructure with
Packit Service 3880ab
.B clang(1)
Packit Service 3880ab
as a C language front end is one project that supports emitting eBPF object
Packit Service 3880ab
files that can be passed to the eBPF classifier (more details in the
Packit Service 3880ab
.B EXAMPLES
Packit Service 3880ab
section). This option is mandatory when an eBPF classifier or action is
Packit Service 3880ab
to be loaded.
Packit Service 3880ab
Packit Service 3880ab
.SS section
Packit Service 3880ab
is the name of the ELF section from the object file, where the eBPF
Packit Service 3880ab
classifier or action resides. By default the section name for the
Packit Service 3880ab
classifier is called "classifier", and for the action "action". Given
Packit Service 3880ab
that a single object file can contain multiple classifier and actions,
Packit Service 3880ab
the corresponding section name needs to be specified, if it differs
Packit Service 3880ab
from the defaults.
Packit Service 3880ab
Packit Service 3880ab
.SS export
Packit Service 3880ab
points to a Unix domain socket file. In case the eBPF object file also
Packit Service 3880ab
contains a section named "maps" with eBPF map specifications, then the
Packit Service 3880ab
map file descriptors can be handed off via the Unix domain socket to
Packit Service 3880ab
an eBPF "agent" herding all descriptors after tc lifetime. This can be
Packit Service 3880ab
some third party application implementing the IPC counterpart for the
Packit Service 3880ab
import, that uses them for calling into
Packit Service 3880ab
.B bpf(2)
Packit Service 3880ab
system call to read out or update eBPF map data from user space, for
Packit Service 3880ab
example, for monitoring purposes or to push down new policies.
Packit Service 3880ab
Packit Service 3880ab
.SS verbose
Packit Service 3880ab
if set, it will dump the eBPF verifier output, even if loading the eBPF
Packit Service 3880ab
program was successful. By default, only on error, the verifier log is
Packit Service 3880ab
being emitted to the user.
Packit Service 3880ab
Packit Service 3880ab
.SS direct-action | da
Packit Service 3880ab
instructs eBPF classifier to not invoke external TC actions, instead use the
Packit Service 3880ab
TC actions return codes (\fBTC_ACT_OK\fR, \fBTC_ACT_SHOT\fR etc.) for
Packit Service 3880ab
classifiers.
Packit Service 3880ab
Packit Service 3880ab
.SS skip_hw | skip_sw
Packit Service 3880ab
hardware offload control flags. By default TC will try to offload
Packit Service 3880ab
filters to hardware if possible.
Packit Service 3880ab
.B skip_hw
Packit Service 3880ab
explicitly disables the attempt to offload.
Packit Service 3880ab
.B skip_sw
Packit Service 3880ab
forces the offload and disables running the eBPF program in the kernel.
Packit Service 3880ab
If hardware offload is not possible and this flag was set kernel will
Packit Service 3880ab
report an error and filter will not be installed at all.
Packit Service 3880ab
Packit Service 3880ab
.SS police
Packit Service 3880ab
is an optional parameter for an eBPF/cBPF classifier that specifies a
Packit Service 3880ab
police in
Packit Service 3880ab
.B tc(1)
Packit Service 3880ab
which is attached to the classifier, for example, on an ingress qdisc.
Packit Service 3880ab
Packit Service 3880ab
.SS action
Packit Service 3880ab
is an optional parameter for an eBPF/cBPF classifier that specifies a
Packit Service 3880ab
subsequent action in
Packit Service 3880ab
.B tc(1)
Packit Service 3880ab
which is attached to a classifier.
Packit Service 3880ab
Packit Service 3880ab
.SS classid
Packit Service 3880ab
.SS flowid
Packit Service 3880ab
provides the default traffic control class identifier for this eBPF/cBPF
Packit Service 3880ab
classifier. The default class identifier can also be overwritten by the
Packit Service 3880ab
return code of the eBPF/cBPF program. A default return code of
Packit Service 3880ab
.B -1
Packit Service 3880ab
specifies the here provided default class identifier to be used. A return
Packit Service 3880ab
code of the eBPF/cBPF program of 0 implies that no match took place, and
Packit Service 3880ab
a return code other than these two will override the default classid. This
Packit Service 3880ab
allows for efficient, non-linear classification with only a single eBPF/cBPF
Packit Service 3880ab
program as opposed to having multiple individual programs for various class
Packit Service 3880ab
identifiers which would need to reparse packet contents.
Packit Service 3880ab
Packit Service 3880ab
.SS bytecode
Packit Service 3880ab
is being used for loading cBPF classifier and actions only. The cBPF bytecode
Packit Service 3880ab
is directly passed as a text string in the form of
Packit Service 3880ab
.B \'s,c t f k,c t f k,c t f k,...\'
Packit Service 3880ab
, where
Packit Service 3880ab
.B s
Packit Service 3880ab
denotes the number of subsequent 4-tuples. One such 4-tuple consists of
Packit Service 3880ab
.B c t f k
Packit Service 3880ab
decimals, where
Packit Service 3880ab
.B c
Packit Service 3880ab
represents the cBPF opcode,
Packit Service 3880ab
.B t
Packit Service 3880ab
the jump true offset target,
Packit Service 3880ab
.B f
Packit Service 3880ab
the jump false offset target and
Packit Service 3880ab
.B k
Packit Service 3880ab
the immediate constant/literal. There are various tools that generate code
Packit Service 3880ab
in this loadable format, for example,
Packit Service 3880ab
.B bpf_asm
Packit Service 3880ab
that ships with the Linux kernel source tree under
Packit Service 3880ab
.B tools/net/
Packit Service 3880ab
, so it is certainly not expected to hack this by hand. The
Packit Service 3880ab
.B bytecode
Packit Service 3880ab
or
Packit Service 3880ab
.B bytecode-file
Packit Service 3880ab
option is mandatory when a cBPF classifier or action is to be loaded.
Packit Service 3880ab
Packit Service 3880ab
.SS bytecode-file
Packit Service 3880ab
also being used to load a cBPF classifier or action. It's effectively the
Packit Service 3880ab
same as
Packit Service 3880ab
.B bytecode
Packit Service 3880ab
only that the cBPF bytecode is not passed directly via command line, but
Packit Service 3880ab
rather resides in a text file.
Packit Service 3880ab
Packit Service 3880ab
.SH EXAMPLES
Packit Service 3880ab
.SS eBPF TOOLING
Packit Service 3880ab
A full blown example including eBPF agent code can be found inside the
Packit Service 3880ab
iproute2 source package under:
Packit Service 3880ab
.B examples/bpf/
Packit Service 3880ab
Packit Service 3880ab
As prerequisites, the kernel needs to have the eBPF system call namely
Packit Service 3880ab
.B bpf(2)
Packit Service 3880ab
enabled and ships with
Packit Service 3880ab
.B cls_bpf
Packit Service 3880ab
and
Packit Service 3880ab
.B act_bpf
Packit Service 3880ab
kernel modules for the traffic control subsystem. To enable eBPF/eBPF JIT
Packit Service 3880ab
support, depending which of the two the given architecture supports:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B echo 1 > /proc/sys/net/core/bpf_jit_enable
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
A given restricted C file can be compiled via LLVM as:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B clang -O2 -emit-llvm -c bpf.c -o - | llc -march=bpf -filetype=obj -o bpf.o
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
The compiler invocation might still simplify in future, so for now,
Packit Service 3880ab
it's quite handy to alias this construct in one way or another, for
Packit Service 3880ab
example:
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
__bcc() {
Packit Service 3880ab
        clang -O2 -emit-llvm -c $1 -o - | \\
Packit Service 3880ab
        llc -march=bpf -filetype=obj -o "`basename $1 .c`.o"
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
alias bcc=__bcc
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
A minimal, stand-alone unit, which matches on all traffic with the
Packit Service 3880ab
default classid (return code of -1) looks like:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
#include <linux/bpf.h>
Packit Service 3880ab
Packit Service 3880ab
#ifndef __section
Packit Service 3880ab
# define __section(x)  __attribute__((section(x), used))
Packit Service 3880ab
#endif
Packit Service 3880ab
Packit Service 3880ab
__section("classifier") int cls_main(struct __sk_buff *skb)
Packit Service 3880ab
{
Packit Service 3880ab
        return -1;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
char __license[] __section("license") = "GPL";
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
More examples can be found further below in subsection
Packit Service 3880ab
.B eBPF PROGRAMMING
Packit Service 3880ab
as focus here will be on tooling.
Packit Service 3880ab
Packit Service 3880ab
There can be various other sections, for example, also for actions.
Packit Service 3880ab
Thus, an object file in eBPF can contain multiple entrance points.
Packit Service 3880ab
Always a specific entrance point, however, must be specified when
Packit Service 3880ab
configuring with tc. A license must be part of the restricted C code
Packit Service 3880ab
and the license string syntax is the same as with Linux kernel modules.
Packit Service 3880ab
The kernel reserves its right that some eBPF helper functions can be
Packit Service 3880ab
restricted to GPL compatible licenses only, and thus may reject a program
Packit Service 3880ab
from loading into the kernel when such a license mismatch occurs.
Packit Service 3880ab
Packit Service 3880ab
The resulting object file from the compilation can be inspected with
Packit Service 3880ab
the usual set of tools that also operate on normal object files, for
Packit Service 3880ab
example
Packit Service 3880ab
.B objdump(1)
Packit Service 3880ab
for inspecting ELF section headers:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
objdump -h bpf.o
Packit Service 3880ab
[...]
Packit Service 3880ab
3 classifier    000007f8  0000000000000000  0000000000000000  00000040  2**3
Packit Service 3880ab
                CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
Packit Service 3880ab
4 action-mark   00000088  0000000000000000  0000000000000000  00000838  2**3
Packit Service 3880ab
                CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
Packit Service 3880ab
5 action-rand   00000098  0000000000000000  0000000000000000  000008c0  2**3
Packit Service 3880ab
                CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
Packit Service 3880ab
6 maps          00000030  0000000000000000  0000000000000000  00000958  2**2
Packit Service 3880ab
                CONTENTS, ALLOC, LOAD, DATA
Packit Service 3880ab
7 license       00000004  0000000000000000  0000000000000000  00000988  2**0
Packit Service 3880ab
                CONTENTS, ALLOC, LOAD, DATA
Packit Service 3880ab
[...]
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Adding an eBPF classifier from an object file that contains a classifier
Packit Service 3880ab
in the default ELF section is trivial (note that instead of "object-file"
Packit Service 3880ab
also shortcuts such as "obj" can be used):
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B bcc bpf.c
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf obj bpf.o flowid 1:1
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
In case the classifier resides in ELF section "mycls", then that same
Packit Service 3880ab
command needs to be invoked as:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf obj bpf.o sec mycls flowid 1:1
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Dumping the classifier configuration will tell the location of the
Packit Service 3880ab
classifier, in other words that it's from object file "bpf.o" under
Packit Service 3880ab
section "mycls":
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc filter show dev em1
Packit Service 3880ab
.br
Packit Service 3880ab
.B filter parent 1: protocol all pref 49152 bpf
Packit Service 3880ab
.br
Packit Service 3880ab
.B filter parent 1: protocol all pref 49152 bpf handle 0x1 flowid 1:1 bpf.o:[mycls]
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
The same program can also be installed on ingress qdisc side as opposed
Packit Service 3880ab
to egress ...
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc qdisc add dev em1 handle ffff: ingress
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc filter add dev em1 parent ffff: bpf obj bpf.o sec mycls flowid ffff:1
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
\&... and again dumped from there:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc filter show dev em1 parent ffff:
Packit Service 3880ab
.br
Packit Service 3880ab
.B filter protocol all pref 49152 bpf
Packit Service 3880ab
.br
Packit Service 3880ab
.B filter protocol all pref 49152 bpf handle 0x1 flowid ffff:1 bpf.o:[mycls]
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Attaching a classifier and action on ingress has the restriction that
Packit Service 3880ab
it doesn't have an actual underlying queueing discipline. What ingress
Packit Service 3880ab
can do is to classify, mangle, redirect or drop packets. When queueing
Packit Service 3880ab
is required on ingress side, then ingress must redirect packets to the
Packit Service 3880ab
.B ifb
Packit Service 3880ab
device, otherwise policing can be used. Moreover, ingress can be used to
Packit Service 3880ab
have an early drop point of unwanted packets before they hit upper layers
Packit Service 3880ab
of the networking stack, perform network accounting with eBPF maps that
Packit Service 3880ab
could be shared with egress, or have an early mangle and/or redirection
Packit Service 3880ab
point to different networking devices.
Packit Service 3880ab
Packit Service 3880ab
Multiple eBPF actions and classifier can be placed into a single
Packit Service 3880ab
object file within various sections. In that case, non-default section
Packit Service 3880ab
names must be provided, which is the case for both actions in this
Packit Service 3880ab
example:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf obj bpf.o flowid 1:1 \e
Packit Service 3880ab
.br
Packit Service 3880ab
.in +25n
Packit Service 3880ab
.B                          action bpf obj bpf.o sec action-mark \e
Packit Service 3880ab
.br
Packit Service 3880ab
.B                          action bpf obj bpf.o sec action-rand ok
Packit Service 3880ab
.in -25n
Packit Service 3880ab
.in -4n
Packit Service 3880ab
Packit Service 3880ab
The advantage of this is that the classifier and the two actions can
Packit Service 3880ab
then share eBPF maps with each other, if implemented in the programs.
Packit Service 3880ab
Packit Service 3880ab
In order to access eBPF maps from user space beyond
Packit Service 3880ab
.B tc(8)
Packit Service 3880ab
setup lifetime, the ownership can be transferred to an eBPF agent via
Packit Service 3880ab
Unix domain sockets. There are two possibilities for implementing this:
Packit Service 3880ab
Packit Service 3880ab
.B 1)
Packit Service 3880ab
implementation of an own eBPF agent that takes care of setting up
Packit Service 3880ab
the Unix domain socket and implementing the protocol that
Packit Service 3880ab
.B tc(8)
Packit Service 3880ab
dictates. A code example of this can be found inside the iproute2
Packit Service 3880ab
source package under:
Packit Service 3880ab
.B examples/bpf/
Packit Service 3880ab
Packit Service 3880ab
.B 2)
Packit Service 3880ab
use
Packit Service 3880ab
.B tc exec
Packit Service 3880ab
for transferring the eBPF map file descriptors through a Unix domain
Packit Service 3880ab
socket, and spawning an application such as
Packit Service 3880ab
.B sh(1)
Packit Service 3880ab
\&. This approach's advantage is that tc will place the file descriptors
Packit Service 3880ab
into the environment and thus make them available just like stdin, stdout,
Packit Service 3880ab
stderr file descriptors, meaning, in case user applications run from within
Packit Service 3880ab
this fd-owner shell, they can terminate and restart without losing eBPF
Packit Service 3880ab
maps file descriptors. Example invocation with the previous classifier and
Packit Service 3880ab
action mixture:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc exec bpf imp /tmp/bpf
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf obj bpf.o exp /tmp/bpf flowid 1:1 \e
Packit Service 3880ab
.br
Packit Service 3880ab
.in +25n
Packit Service 3880ab
.B                          action bpf obj bpf.o sec action-mark \e
Packit Service 3880ab
.br
Packit Service 3880ab
.B                          action bpf obj bpf.o sec action-rand ok
Packit Service 3880ab
.in -25n
Packit Service 3880ab
.in -4n
Packit Service 3880ab
Packit Service 3880ab
Assuming that eBPF maps are shared with classifier and actions, it's
Packit Service 3880ab
enough to export them once, for example, from within the classifier
Packit Service 3880ab
or action command. tc will setup all eBPF map file descriptors at the
Packit Service 3880ab
time when the object file is first parsed.
Packit Service 3880ab
Packit Service 3880ab
When a shell has been spawned, the environment will have a couple of
Packit Service 3880ab
eBPF related variables. BPF_NUM_MAPS provides the total number of maps
Packit Service 3880ab
that have been transferred over the Unix domain socket. BPF_MAP<X>'s
Packit Service 3880ab
value is the file descriptor number that can be accessed in eBPF agent
Packit Service 3880ab
applications, in other words, it can directly be used as the file
Packit Service 3880ab
descriptor value for the
Packit Service 3880ab
.B bpf(2)
Packit Service 3880ab
system call to retrieve or alter eBPF map values. <X> denotes the
Packit Service 3880ab
identifier of the eBPF map. It corresponds to the
Packit Service 3880ab
.B id
Packit Service 3880ab
member of
Packit Service 3880ab
.B struct bpf_elf_map
Packit Service 3880ab
\& from the tc eBPF map specification.
Packit Service 3880ab
Packit Service 3880ab
The environment in this example looks as follows:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
sh# env | grep BPF
Packit Service 3880ab
    BPF_NUM_MAPS=3
Packit Service 3880ab
    BPF_MAP1=6
Packit Service 3880ab
    BPF_MAP0=5
Packit Service 3880ab
    BPF_MAP2=7
Packit Service 3880ab
sh# ls -la /proc/self/fd
Packit Service 3880ab
    [...]
Packit Service 3880ab
    lrwx------. 1 root root 64 Apr 14 16:46 5 -> anon_inode:bpf-map
Packit Service 3880ab
    lrwx------. 1 root root 64 Apr 14 16:46 6 -> anon_inode:bpf-map
Packit Service 3880ab
    lrwx------. 1 root root 64 Apr 14 16:46 7 -> anon_inode:bpf-map
Packit Service 3880ab
sh# my_bpf_agent
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
eBPF agents are very useful in that they can prepopulate eBPF maps from
Packit Service 3880ab
user space, monitor statistics via maps and based on that feedback, for
Packit Service 3880ab
example, rewrite classids in eBPF map values during runtime. Given that eBPF
Packit Service 3880ab
agents are implemented as normal applications, they can also dynamically
Packit Service 3880ab
receive traffic control policies from external controllers and thus push
Packit Service 3880ab
them down into eBPF maps to dynamically adapt to network conditions. Moreover,
Packit Service 3880ab
eBPF maps can also be shared with other eBPF program types (e.g. tracing),
Packit Service 3880ab
thus very powerful combination can therefore be implemented.
Packit Service 3880ab
Packit Service 3880ab
.SS eBPF PROGRAMMING
Packit Service 3880ab
Packit Service 3880ab
eBPF classifier and actions are being implemented in restricted C syntax
Packit Service 3880ab
(in future, there could additionally be new language frontends supported).
Packit Service 3880ab
Packit Service 3880ab
The header file
Packit Service 3880ab
.B linux/bpf.h
Packit Service 3880ab
provides eBPF helper functions that can be called from an eBPF program.
Packit Service 3880ab
This man page will only provide two minimal, stand-alone examples, have a
Packit Service 3880ab
look at
Packit Service 3880ab
.B examples/bpf
Packit Service 3880ab
from the iproute2 source package for a fully fledged flow dissector
Packit Service 3880ab
example to better demonstrate some of the possibilities with eBPF.
Packit Service 3880ab
Packit Service 3880ab
Supported 32 bit classifier return codes from the C program and their meanings:
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B 0
Packit Service 3880ab
, denotes a mismatch
Packit Service 3880ab
.br
Packit Service 3880ab
.B -1
Packit Service 3880ab
, denotes the default classid configured from the command line
Packit Service 3880ab
.br
Packit Service 3880ab
.B else
Packit Service 3880ab
, everything else will override the default classid to provide a facility for
Packit Service 3880ab
non-linear matching
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Supported 32 bit action return codes from the C program and their meanings (
Packit Service 3880ab
.B linux/pkt_cls.h
Packit Service 3880ab
):
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B TC_ACT_OK (0)
Packit Service 3880ab
, will terminate the packet processing pipeline and allows the packet to
Packit Service 3880ab
proceed
Packit Service 3880ab
.br
Packit Service 3880ab
.B TC_ACT_SHOT (2)
Packit Service 3880ab
, will terminate the packet processing pipeline and drops the packet
Packit Service 3880ab
.br
Packit Service 3880ab
.B TC_ACT_UNSPEC (-1)
Packit Service 3880ab
, will use the default action configured from tc (similarly as returning
Packit Service 3880ab
.B -1
Packit Service 3880ab
from a classifier)
Packit Service 3880ab
.br
Packit Service 3880ab
.B TC_ACT_PIPE (3)
Packit Service 3880ab
, will iterate to the next action, if available
Packit Service 3880ab
.br
Packit Service 3880ab
.B TC_ACT_RECLASSIFY (1)
Packit Service 3880ab
, will terminate the packet processing pipeline and start classification
Packit Service 3880ab
from the beginning
Packit Service 3880ab
.br
Packit Service 3880ab
.B else
Packit Service 3880ab
, everything else is an unspecified return code
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Both classifier and action return codes are supported in eBPF and cBPF
Packit Service 3880ab
programs.
Packit Service 3880ab
Packit Service 3880ab
To demonstrate restricted C syntax, a minimal toy classifier example is
Packit Service 3880ab
provided, which assumes that egress packets, for instance originating
Packit Service 3880ab
from a container, have previously been marked in interval [0, 255]. The
Packit Service 3880ab
program keeps statistics on different marks for user space and maps the
Packit Service 3880ab
classid to the root qdisc with the marking itself as the minor handle:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
#include <stdint.h>
Packit Service 3880ab
#include <asm/types.h>
Packit Service 3880ab
Packit Service 3880ab
#include <linux/bpf.h>
Packit Service 3880ab
#include <linux/pkt_sched.h>
Packit Service 3880ab
Packit Service 3880ab
#include "helpers.h"
Packit Service 3880ab
Packit Service 3880ab
struct tuple {
Packit Service 3880ab
        long packets;
Packit Service 3880ab
        long bytes;
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
#define BPF_MAP_ID_STATS        1 /* agent's map identifier */
Packit Service 3880ab
#define BPF_MAX_MARK            256
Packit Service 3880ab
Packit Service 3880ab
struct bpf_elf_map __section("maps") map_stats = {
Packit Service 3880ab
        .type           =       BPF_MAP_TYPE_ARRAY,
Packit Service 3880ab
        .id             =       BPF_MAP_ID_STATS,
Packit Service 3880ab
        .size_key       =       sizeof(uint32_t),
Packit Service 3880ab
        .size_value     =       sizeof(struct tuple),
Packit Service 3880ab
        .max_elem       =       BPF_MAX_MARK,
Packit Service 3880ab
        .pinning        =       PIN_GLOBAL_NS,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static inline void cls_update_stats(const struct __sk_buff *skb,
Packit Service 3880ab
                                    uint32_t mark)
Packit Service 3880ab
{
Packit Service 3880ab
        struct tuple *tu;
Packit Service 3880ab
Packit Service 3880ab
        tu = bpf_map_lookup_elem(&map_stats, &mark);
Packit Service 3880ab
        if (likely(tu)) {
Packit Service 3880ab
                __sync_fetch_and_add(&tu->packets, 1);
Packit Service 3880ab
                __sync_fetch_and_add(&tu->bytes, skb->len);
Packit Service 3880ab
        }
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
__section("cls") int cls_main(struct __sk_buff *skb)
Packit Service 3880ab
{
Packit Service 3880ab
        uint32_t mark = skb->mark;
Packit Service 3880ab
Packit Service 3880ab
        if (unlikely(mark >= BPF_MAX_MARK))
Packit Service 3880ab
                return 0;
Packit Service 3880ab
Packit Service 3880ab
        cls_update_stats(skb, mark);
Packit Service 3880ab
Packit Service 3880ab
        return TC_H_MAKE(TC_H_ROOT, mark);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
char __license[] __section("license") = "GPL";
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Another small example is a port redirector which demuxes destination port
Packit Service 3880ab
80 into the interval [8080, 8087] steered by RSS, that can then be attached
Packit Service 3880ab
to ingress qdisc. The exercise of adding the egress counterpart and IPv6
Packit Service 3880ab
support is left to the reader:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
#include <asm/types.h>
Packit Service 3880ab
#include <asm/byteorder.h>
Packit Service 3880ab
Packit Service 3880ab
#include <linux/bpf.h>
Packit Service 3880ab
#include <linux/filter.h>
Packit Service 3880ab
#include <linux/in.h>
Packit Service 3880ab
#include <linux/if_ether.h>
Packit Service 3880ab
#include <linux/ip.h>
Packit Service 3880ab
#include <linux/tcp.h>
Packit Service 3880ab
Packit Service 3880ab
#include "helpers.h"
Packit Service 3880ab
Packit Service 3880ab
static inline void set_tcp_dport(struct __sk_buff *skb, int nh_off,
Packit Service 3880ab
                                 __u16 old_port, __u16 new_port)
Packit Service 3880ab
{
Packit Service 3880ab
        bpf_l4_csum_replace(skb, nh_off + offsetof(struct tcphdr, check),
Packit Service 3880ab
                            old_port, new_port, sizeof(new_port));
Packit Service 3880ab
        bpf_skb_store_bytes(skb, nh_off + offsetof(struct tcphdr, dest),
Packit Service 3880ab
                            &new_port, sizeof(new_port), 0);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static inline int lb_do_ipv4(struct __sk_buff *skb, int nh_off)
Packit Service 3880ab
{
Packit Service 3880ab
        __u16 dport, dport_new = 8080, off;
Packit Service 3880ab
        __u8 ip_proto, ip_vl;
Packit Service 3880ab
Packit Service 3880ab
        ip_proto = load_byte(skb, nh_off +
Packit Service 3880ab
                             offsetof(struct iphdr, protocol));
Packit Service 3880ab
        if (ip_proto != IPPROTO_TCP)
Packit Service 3880ab
                return 0;
Packit Service 3880ab
Packit Service 3880ab
        ip_vl = load_byte(skb, nh_off);
Packit Service 3880ab
        if (likely(ip_vl == 0x45))
Packit Service 3880ab
                nh_off += sizeof(struct iphdr);
Packit Service 3880ab
        else
Packit Service 3880ab
                nh_off += (ip_vl & 0xF) << 2;
Packit Service 3880ab
Packit Service 3880ab
        dport = load_half(skb, nh_off + offsetof(struct tcphdr, dest));
Packit Service 3880ab
        if (dport != 80)
Packit Service 3880ab
                return 0;
Packit Service 3880ab
Packit Service 3880ab
        off = skb->queue_mapping & 7;
Packit Service 3880ab
        set_tcp_dport(skb, nh_off - BPF_LL_OFF, __constant_htons(80),
Packit Service 3880ab
                      __cpu_to_be16(dport_new + off));
Packit Service 3880ab
        return -1;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
__section("lb") int lb_main(struct __sk_buff *skb)
Packit Service 3880ab
{
Packit Service 3880ab
        int ret = 0, nh_off = BPF_LL_OFF + ETH_HLEN;
Packit Service 3880ab
Packit Service 3880ab
        if (likely(skb->protocol == __constant_htons(ETH_P_IP)))
Packit Service 3880ab
                ret = lb_do_ipv4(skb, nh_off);
Packit Service 3880ab
Packit Service 3880ab
        return ret;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
char __license[] __section("license") = "GPL";
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
The related helper header file
Packit Service 3880ab
.B helpers.h
Packit Service 3880ab
in both examples was:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
/* Misc helper macros. */
Packit Service 3880ab
#define __section(x) __attribute__((section(x), used))
Packit Service 3880ab
#define offsetof(x, y) __builtin_offsetof(x, y)
Packit Service 3880ab
#define likely(x) __builtin_expect(!!(x), 1)
Packit Service 3880ab
#define unlikely(x) __builtin_expect(!!(x), 0)
Packit Service 3880ab
Packit Service 3880ab
/* Object pinning settings */
Packit Service 3880ab
#define PIN_NONE       0
Packit Service 3880ab
#define PIN_OBJECT_NS  1
Packit Service 3880ab
#define PIN_GLOBAL_NS  2
Packit Service 3880ab
Packit Service 3880ab
/* ELF map definition */
Packit Service 3880ab
struct bpf_elf_map {
Packit Service 3880ab
    __u32 type;
Packit Service 3880ab
    __u32 size_key;
Packit Service 3880ab
    __u32 size_value;
Packit Service 3880ab
    __u32 max_elem;
Packit Service 3880ab
    __u32 flags;
Packit Service 3880ab
    __u32 id;
Packit Service 3880ab
    __u32 pinning;
Packit Service 3880ab
    __u32 inner_id;
Packit Service 3880ab
    __u32 inner_idx;
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
/* Some used BPF function calls. */
Packit Service 3880ab
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from,
Packit Service 3880ab
                                  int len, int flags) =
Packit Service 3880ab
      (void *) BPF_FUNC_skb_store_bytes;
Packit Service 3880ab
static int (*bpf_l4_csum_replace)(void *ctx, int off, int from,
Packit Service 3880ab
                                  int to, int flags) =
Packit Service 3880ab
      (void *) BPF_FUNC_l4_csum_replace;
Packit Service 3880ab
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
Packit Service 3880ab
      (void *) BPF_FUNC_map_lookup_elem;
Packit Service 3880ab
Packit Service 3880ab
/* Some used BPF intrinsics. */
Packit Service 3880ab
unsigned long long load_byte(void *skb, unsigned long long off)
Packit Service 3880ab
    asm ("llvm.bpf.load.byte");
Packit Service 3880ab
unsigned long long load_half(void *skb, unsigned long long off)
Packit Service 3880ab
    asm ("llvm.bpf.load.half");
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Best practice, we recommend to only have a single eBPF classifier loaded
Packit Service 3880ab
in tc and perform
Packit Service 3880ab
.B all
Packit Service 3880ab
necessary matching and mangling from there instead of a list of individual
Packit Service 3880ab
classifier and separate actions. Just a single classifier tailored for a
Packit Service 3880ab
given use-case will be most efficient to run.
Packit Service 3880ab
Packit Service 3880ab
.SS eBPF DEBUGGING
Packit Service 3880ab
Packit Service 3880ab
Both tc
Packit Service 3880ab
.B filter
Packit Service 3880ab
and
Packit Service 3880ab
.B action
Packit Service 3880ab
commands for
Packit Service 3880ab
.B bpf
Packit Service 3880ab
support an optional
Packit Service 3880ab
.B verbose
Packit Service 3880ab
parameter that can be used to inspect the eBPF verifier log. It is dumped
Packit Service 3880ab
by default in case of an error.
Packit Service 3880ab
Packit Service 3880ab
In case the eBPF/cBPF JIT compiler has been enabled, it can also be
Packit Service 3880ab
instructed to emit a debug output of the resulting opcode image into
Packit Service 3880ab
the kernel log, which can be read via
Packit Service 3880ab
.B dmesg(1)
Packit Service 3880ab
:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B echo 2 > /proc/sys/net/core/bpf_jit_enable
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
The Linux kernel source tree ships additionally under
Packit Service 3880ab
.B tools/net/
Packit Service 3880ab
a small helper called
Packit Service 3880ab
.B bpf_jit_disasm
Packit Service 3880ab
that reads out the opcode image dump from the kernel log and dumps the
Packit Service 3880ab
resulting disassembly:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B bpf_jit_disasm -o
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Other than that, the Linux kernel also contains an extensive eBPF/cBPF
Packit Service 3880ab
test suite module called
Packit Service 3880ab
.B test_bpf
Packit Service 3880ab
\&. Upon ...
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B modprobe test_bpf
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
\&... it performs a diversity of test cases and dumps the results into
Packit Service 3880ab
the kernel log that can be inspected with
Packit Service 3880ab
.B dmesg(1)
Packit Service 3880ab
\&. The results can differ depending on whether the JIT compiler is enabled
Packit Service 3880ab
or not. In case of failed test cases, the module will fail to load. In
Packit Service 3880ab
such cases, we urge you to file a bug report to the related JIT authors,
Packit Service 3880ab
Linux kernel and networking mailing lists.
Packit Service 3880ab
Packit Service 3880ab
.SS cBPF
Packit Service 3880ab
Packit Service 3880ab
Although we generally recommend switching to implementing
Packit Service 3880ab
.B eBPF
Packit Service 3880ab
classifier and actions, for the sake of completeness, a few words on how to
Packit Service 3880ab
program in cBPF will be lost here.
Packit Service 3880ab
Packit Service 3880ab
Likewise, the
Packit Service 3880ab
.B bpf_jit_enable
Packit Service 3880ab
switch can be enabled as mentioned already. Tooling such as
Packit Service 3880ab
.B bpf_jit_disasm
Packit Service 3880ab
is also independent whether eBPF or cBPF code is being loaded.
Packit Service 3880ab
Packit Service 3880ab
Unlike in eBPF, classifier and action are not implemented in restricted C,
Packit Service 3880ab
but rather in a minimal assembler-like language or with the help of other
Packit Service 3880ab
tooling.
Packit Service 3880ab
Packit Service 3880ab
The raw interface with tc takes opcodes directly. For example, the most
Packit Service 3880ab
minimal classifier matching on every packet resulting in the default
Packit Service 3880ab
classid of 1:1 looks like:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf bytecode '1,6 0 0 4294967295,' flowid 1:1
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
The first decimal of the bytecode sequence denotes the number of subsequent
Packit Service 3880ab
4-tuples of cBPF opcodes. As mentioned, such a 4-tuple consists of
Packit Service 3880ab
.B c t f k
Packit Service 3880ab
decimals, where
Packit Service 3880ab
.B c
Packit Service 3880ab
represents the cBPF opcode,
Packit Service 3880ab
.B t
Packit Service 3880ab
the jump true offset target,
Packit Service 3880ab
.B f
Packit Service 3880ab
the jump false offset target and
Packit Service 3880ab
.B k
Packit Service 3880ab
the immediate constant/literal. Here, this denotes an unconditional return
Packit Service 3880ab
from the program with immediate value of -1.
Packit Service 3880ab
Packit Service 3880ab
Thus, for egress classification, Willem de Bruijn implemented a minimal stand-alone
Packit Service 3880ab
helper tool under the GNU General Public License version 2 for
Packit Service 3880ab
.B iptables(8)
Packit Service 3880ab
BPF extension, which abuses the
Packit Service 3880ab
.B libpcap
Packit Service 3880ab
internal classic BPF compiler, his code derived here for usage with
Packit Service 3880ab
.B tc(8)
Packit Service 3880ab
:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
#include <pcap.h>
Packit Service 3880ab
#include <stdio.h>
Packit Service 3880ab
Packit Service 3880ab
int main(int argc, char **argv)
Packit Service 3880ab
{
Packit Service 3880ab
        struct bpf_program prog;
Packit Service 3880ab
        struct bpf_insn *ins;
Packit Service 3880ab
        int i, ret, dlt = DLT_RAW;
Packit Service 3880ab
Packit Service 3880ab
        if (argc < 2 || argc > 3)
Packit Service 3880ab
                return 1;
Packit Service 3880ab
        if (argc == 3) {
Packit Service 3880ab
                dlt = pcap_datalink_name_to_val(argv[1]);
Packit Service 3880ab
                if (dlt == -1)
Packit Service 3880ab
                        return 1;
Packit Service 3880ab
        }
Packit Service 3880ab
Packit Service 3880ab
        ret = pcap_compile_nopcap(-1, dlt, &prog, argv[argc - 1],
Packit Service 3880ab
                                  1, PCAP_NETMASK_UNKNOWN);
Packit Service 3880ab
        if (ret)
Packit Service 3880ab
                return 1;
Packit Service 3880ab
Packit Service 3880ab
        printf("%d,", prog.bf_len);
Packit Service 3880ab
        ins = prog.bf_insns;
Packit Service 3880ab
Packit Service 3880ab
        for (i = 0; i < prog.bf_len - 1; ++ins, ++i)
Packit Service 3880ab
                printf("%u %u %u %u,", ins->code,
Packit Service 3880ab
                       ins->jt, ins->jf, ins->k);
Packit Service 3880ab
        printf("%u %u %u %u",
Packit Service 3880ab
               ins->code, ins->jt, ins->jf, ins->k);
Packit Service 3880ab
Packit Service 3880ab
        pcap_freecode(&prog;;
Packit Service 3880ab
        return 0;
Packit Service 3880ab
}
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Given this small helper, any
Packit Service 3880ab
.B tcpdump(8)
Packit Service 3880ab
filter expression can be abused as a classifier where a match will
Packit Service 3880ab
result in the default classid:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B bpftool EN10MB 'tcp[tcpflags] & tcp-syn != 0' > /var/bpf/tcp-syn
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf bytecode-file /var/bpf/tcp-syn flowid 1:1
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Basically, such a minimal generator is equivalent to:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B tcpdump -iem1 -ddd 'tcp[tcpflags] & tcp-syn != 0' | tr '\\\\n' ',' > /var/bpf/tcp-syn
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Since
Packit Service 3880ab
.B libpcap
Packit Service 3880ab
does not support all Linux' specific cBPF extensions in its compiler, the
Packit Service 3880ab
Linux kernel also ships under
Packit Service 3880ab
.B tools/net/
Packit Service 3880ab
a minimal BPF assembler called
Packit Service 3880ab
.B bpf_asm
Packit Service 3880ab
for providing full control. For detailed syntax and semantics on implementing
Packit Service 3880ab
such programs by hand, see references under
Packit Service 3880ab
.B FURTHER READING
Packit Service 3880ab
\&.
Packit Service 3880ab
Packit Service 3880ab
Trivial toy example in
Packit Service 3880ab
.B bpf_asm
Packit Service 3880ab
for classifying IPv4/TCP packets, saved in a text file called
Packit Service 3880ab
.B foobar
Packit Service 3880ab
:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.nf
Packit Service 3880ab
.sp
Packit Service 3880ab
ldh [12]
Packit Service 3880ab
jne #0x800, drop
Packit Service 3880ab
ldb [23]
Packit Service 3880ab
jneq #6, drop
Packit Service 3880ab
ret #-1
Packit Service 3880ab
drop: ret #0
Packit Service 3880ab
.fi
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
Similarly, such a classifier can be loaded as:
Packit Service 3880ab
Packit Service 3880ab
.in +4n
Packit Service 3880ab
.B bpf_asm foobar > /var/bpf/tcp-syn
Packit Service 3880ab
.br
Packit Service 3880ab
.B tc filter add dev em1 parent 1: bpf bytecode-file /var/bpf/tcp-syn flowid 1:1
Packit Service 3880ab
.in
Packit Service 3880ab
Packit Service 3880ab
For BPF classifiers, the Linux kernel provides additionally under
Packit Service 3880ab
.B tools/net/
Packit Service 3880ab
a small BPF debugger called
Packit Service 3880ab
.B bpf_dbg
Packit Service 3880ab
, which can be used to test a classifier against pcap files, single-step
Packit Service 3880ab
or add various breakpoints into the classifier program and dump register
Packit Service 3880ab
contents during runtime.
Packit Service 3880ab
Packit Service 3880ab
Implementing an action in classic BPF is rather limited in the sense that
Packit Service 3880ab
packet mangling is not supported. Therefore, it's generally recommended to
Packit Service 3880ab
make the switch to eBPF, whenever possible.
Packit Service 3880ab
Packit Service 3880ab
.SH FURTHER READING
Packit Service 3880ab
Further and more technical details about the BPF architecture can be found
Packit Service 3880ab
in the Linux kernel source tree under
Packit Service 3880ab
.B Documentation/networking/filter.txt
Packit Service 3880ab
\&.
Packit Service 3880ab
Packit Service 3880ab
Further details on eBPF
Packit Service 3880ab
.B tc(8)
Packit Service 3880ab
examples can be found in the iproute2 source
Packit Service 3880ab
tree under
Packit Service 3880ab
.B examples/bpf/
Packit Service 3880ab
\&.
Packit Service 3880ab
Packit Service 3880ab
.SH SEE ALSO
Packit Service 3880ab
.BR tc (8),
Packit Service 3880ab
.BR tc-ematch (8)
Packit Service 3880ab
.BR bpf (2)
Packit Service 3880ab
.BR bpf (4)
Packit Service 3880ab
Packit Service 3880ab
.SH AUTHORS
Packit Service 3880ab
Manpage written by Daniel Borkmann.
Packit Service 3880ab
Packit Service 3880ab
Please report corrections or improvements to the Linux kernel networking
Packit Service 3880ab
mailing list:
Packit Service 3880ab
.B <netdev@vger.kernel.org>