[tcpdump-workers] BPF Extended: addressing BPF's shortcomings

Mindaugas Rasiukevicius rmind at noxt.eu
Wed Jun 10 19:31:49 EDT 2015

Darren Reed <darrenr at netbsd.org> wrote:
> Extending BPF
> =============
> Introduction
> ------------
> BPF was originally designed to provide very fast packet matching
> capabilities for IPv4 but as a result of its generic nature, is
> capable of being used for just about any protocol. With IPv6 the
> limitations of BPF became apparent.
> ...

Conceptually, I like the idea of an extended BPF instruction set.  There
are several important questions here.  First, what is the exact problem we
want to solve with a new instruction set?  Is it just the IPv6 handling?

I do find the BPF byte-code useful as a general purpose instruction set
i.e. for the use as a universal virtual machine.  This was also one of the
driving forces behind the Linux eBPF.  They use it beyond packet filtering.
Note that LLVM has recently gained support for the eBPF backend.  If that
is the objective, then there is a wider spectrum of the requirements.

Specifically, I would like to see:

- Capability to jump backwards.  Basically, the general purpose instruction
set ought be Turing-complete.  Obviously, with a way to enable/disable this
depending whether the user needs bpf_validate().

- 32-bit jump offsets.  Currently, they are 16-bit which is quite limiting
if you have a larger BPF program.

- Opcode extended to 32-bits.  It seems we agree on this, although this
can be debatable.  The classic BPF byte-code has a simple, minimalistic
RISC-like instruction set (with the exception of BPF_MSH hack).  I would
be inclined to keep it that way instead of polluting the, quite limited,
instruction space with various arbitrary mechanisms, but this is somewhat
philosophical RISC vs CISC debate.  Nevertheless, if the general feeling
is to go with complex instructions, then we could at least dedicate a wide
range for them.

- Support for 64-bit words, but not quite convinced about 128-bit words.
Do you want to add them just to accommodate IPv6?  Why not to leave this
for the byte-code generator/compiler?

- External scratch memory store or a way to initialise it before calling
the BPF program.  Also, potentially arbitrary (dynamic) BPF_MEMWORDS size
rather than hardcoded size.  Basically, the user/caller should be able to
provide arbitrary data through the memory store.

- BPF_COP and BPF_CALL.  When I added BPF_COP to NetBSD, I thought about
the generic BPF_CALL to invoke *arbitrary* functions.  It requires solving
some of the above problems first, but there is an important difference:
BPF_COP allows program to invoke a *predetermined* set of functions, while
the capability to invoke arbitrary functions through BPF_CALL can have
security implications (yet it is more powerful).  I would like to see both,
but with the ability to disable, at least, BPF_CALL.

Another point to consider, besides the JIT compilation, is API level
backwards compatibility with the classic BPF instruction set.  Having at
least partially compatible instruction set would ease the migration for
the existing BPF byte-code generators/compilers.

Last, but not least, how does this all fit in the libpcap/tcpdump project?
Are the project goals exclusively limited to capturing the network traffic
or there is a desire to abstract parts of libpcap into some more generic
libbpf?  Also, given that Linux eBPF is gaining the momentum, how realistic
is to push a competing instruction set?


More information about the tcpdump-workers mailing list